1. 程式人生 > 實用技巧 >【016期】JavaSE面試題(十六):反射

【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 方法

,但注意的是代理的是介面,也就是你的業務類必須要實現介面,通過 Proxy 裡的 newProxyInstance 得到代理物件。
還有一種動態代理 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")