類型與反射

對於類型與反射,我的理解是在運行時可以動態地對類進行一些操作。

比如:XXX x = new XXX() 這個 XXX 我是可以外部輸入的,輸入"Cat" 的時候就是 Cat x = new Cat(),輸入"Dog" 的時候,就是 Dog x = new Dog()

但是這在一般的編程是很難這樣動態地做到的,因此需要反射。

運行 Java 文件的過程

Java 文件的運行過程是這樣的:

xxx.java -> 編譯 -> xxx.class -> 運行

通俗來講,每個類型要變成一份“說明書”(xxx.class),然後在 new XXX() 的時候是根據這份“說明書”來創建對象的。

這不禁讓我們想到:能不能在運行的時候去修改這份說明書,比如加入變量,修改裏面方法等,然後再根據這份“修改過的說明書”去 new 對象呢?

ClassLoader

爲了去更深入想上面的問題,先來看看這個玩意:ClassLoader,它負責從外部加載一個類,也就是我們的 xxx.java -> 編譯 -> xxx.class 這一步。這個很容易理解,就相當於編譯器嘛。

不過它也有下面特點:

  • 對應的 Java 文件不一定存在,可以是 Stream,自己創建 Class
  • 對應的字節碼不一定存在,動態創建 Class

上面的這些特點不禁讓我們想到可以“動態地”修改“說明書”了。

反射

反射就是可以在運行的時候去修改這份說明書的,然後我們可以調用 ClassLoader 去編譯其實就是我們所說的動態XXXX。有了反射,我們可以

  • 動態創建一個對象
  • 動態調用一個方法
  • 動態獲取一個屬性

動態創建一個對象

String className = args[0];

Class c = Class.forName(className);

Object obj = c.getConstructor().newInstance();

動態調用一個方法

Cat cat = new Cat();

cat.getClass().getMethod(args[0]).invoke();

動態獲取一個屬性

Cat cat = new Cat();

cat.getClass().getField(args[0]).get(cat)

雙親委派模型

看名字就看不懂,意思其實很簡單,如果一個類如 String 已經聲明,然後你再別的地方再聲明 String,那你的 String 並不會被加載。僞代碼如下:

if (java.lang 包裏有沒有 String 類被加載?) {
  不管了,直接結束
} else {
  load(自己寫的包的 String 類)
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章