【016期】JavaSE面試題(十六):反射
開篇介紹
大家好,我是Java最全面試題庫
的提褲姐,今天這篇是JavaSE系列的第十六篇,主要總結了Java中反射
相關的問題,在後續,會沿著第一篇開篇的知識線路一直總結下去,做到日更!如果我能做到百日百更,希望你也可以跟著百日百刷,一百天養成一個好習慣。
說說你對 Java 中反射的理解
在執行狀態,
對於任意一個類,都能獲取這個類的所有屬性和方法,
對任意一個物件,都能呼叫它的任意屬性和方法。
這種動態獲取的資訊及動態呼叫物件的方法即為Java的反射。
反射能做什麼
在執行時判斷一個類所具有的成員變數和方法
在執行時判斷任意一個物件所屬的類
在執行時構造一個類的物件
在執行時呼叫任意一個物件的方法
class.forName和classLoader的區別
class.forName:
- 將類的.class檔案載入到jvm中
- 對類進行解釋,執行類中的static塊
classLoader:
- 只幹一件事情:將.class檔案載入到jvm中,不會執行static中的內容,只有在newInstance才會去執行static塊。
Class.forName(className):
內部呼叫的方法是 Class.forName(className,true,classloader);
第2個boolean引數表示類是否需要初始化, Class.forName(className)預設是需要初始化。
一旦初始化,就會觸發目標物件的static塊程式碼執行,static引數也也會被再次初始化。
ClassLoader.loadClass(className):
內部呼叫的方法是ClassLoader.loadClass(className,false);
第2個 boolean引數,表示目標物件是否進行連結,false表示不進行連結,不進行連結意味著不進行包括初始化等一些列步驟,那麼靜態塊和靜態物件就不會得到執行
動靜態代理的區別,什麼場景使用?
靜態代理通常只代理一個類
,動態代理是代理一個介面下的多個實現類
。
靜態代理事先知道要代理的是什麼,而動態代理不知道要代理什麼東西,只有在執行時才知道。
動態代理是實現 JDK 裡的 InvocationHandler
介面的 invoke 方法
還有一種動態代理 CGLIB,代理的是類,不需要業務類繼承介面,通過派生的子類來實現代理。通過在執行時,動態修改位元組碼達到修改類的目的。
AOP 程式設計就是基於動態代理實現的,比如著名的 Spring 框架、Hibernate 框架等等都是動態代理的使用例子。
Java 的類載入器的種類都有哪些?
1、根類載入器(Bootstrap
) --C++寫的 ,看不到原始碼
2、擴充套件類載入器(Extension
) --載入位置 :jre\lib\ext
中
3、系統(應用)類載入器(System\App
) --載入位置 :classpath
中 4、自定義載入器(必須繼承 ClassLoader
)
類什麼時候被初始化?
- 建立類的例項,也就是 new 一個物件
- 訪問某個類或介面的靜態變數,或者對該靜態變數賦值
- 呼叫類的靜態方法
- 反射(
Class.forName("com.hcx.load")
) - 初始化一個類的子類(會首先初始化子類的父類)
- JVM 啟動時標明的啟動類,即檔名和類名相同的那個類
類的初始化步驟:
- 如果這個類還沒有被載入和連結,那先進行載入和連結
- 假如這個類存在直接父類,並且這個類還沒有被初始化(注意:在一個類載入器中,類只能初始化一次),那就初始化直接的父類(不適用於介面)
- 加入類中存在初始化語句(如 static 變數和 static塊),那就依次執行這些初始化語句。
獲得一個類物件有哪些方式?
- 型別.class,例如:
String.class
- 物件.getClass(),例如:
"hello".getClass()
- Class.forName(),例如:
Class.forName("java.lang.String")