關於Java反射的總結


反射的本質就是:在運行時,把 Java 類中的各種成分映射成一個個的 Java 對象。**

0.反射和類加載關係

類加載過程如下:

  1. 編譯,Java 編譯器將 .java 編譯產生 .class 二進制文件。

  2. 加載,JVM 中的類加載器解析.class 文件內的信息。

    類加載器會根據類的全限定名來獲取此類的二進制字節流,生成代表這個類的 java.lang.Class 對象。

  3. 加載結束後,JVM 開始進行連接階段(包含驗證、準備、初始化)。經過這一系列操作,類的變量會被初始化。

  4. 初始化

反射就是上述第二步,**Java 中,無論生成某個類的多少個對象,這些對象都會對應於同一個 Class 對象。**使用反射可獲取class,然後進行各種操作。

  1. JVM 加載方法的時候,遇到 new User(),JVM 會根據 User 的全限定名去加載 User.class 。
  2. JVM 會去本地磁盤查找 User.class 文件並加載 JVM 內存中。
  3. JVM 通過調用類加載器自動創建這個類對應的 Class 對象,並且存儲在 JVM 的方法區。注意:一個類有且只有一個 Class 對象。

1.獲取Class對象的方法

3種:

  • forName

    Class c1 = Class.forName("xxx.xxx.xxx");
    
  • 通過類獲取Class

    Class c2 = Boolean.class;
    
  • 通過對象 getClass

    Boolean bool = new Boolean();
    Class c3 = bool.getClass();
    

2.獲取Class對象的信息

setAccessible() //是一個通用的方法,可獲取到對應信息的超級權限,若當前信息有private等權限控制,該方法可拿到操作權限

構造方法

  • 獲取constructors數組

    cla.getConstructors()
    
  • 獲取constructor

    getConstructor(Class<?>... parameterTypes)
    
  • 獲取非public的構造函數

    getDeclaredConstructor(Class<?>... parameterTypes)
    

使用對象創建實例方式見下

屬性

  • 獲取屬性數組

    getFields()
    
  • 獲取指定Field

    getField(String name)
    
  • 獲取非public的屬性

    getDeclaredField(String name)
    
  • 設置屬性

    set(Object,param)
    

方法

  • 獲取方法數組

    getMethods()
    
  • 獲取指定數組

    getMethod(String name, Class<?>... parameterTypes)
    
  • 獲取非public數組

    getDeclaredMethod(String name, Class<?>... parameterTypes)
    
  • 指定對象調用方法

    invoke(Object)
    

3.反射操作實例對象

判斷是否爲類的實例兩種方式:

  1. 用 instanceof 關鍵字
  2. 用 Class 對象的 isInstance 方法(它是一個 Native 方法)
    ArrayList arrayList = new ArrayList();

		Boolean isList1 = arrayList instanceof List
		Boolean isList2 = List.class.isInstance(arrayList)

創建實例

  1. 用 Class 對象的 newInstance 方法,沒有無參構造函數無法創建,需使用第2種。
  2. 用 Constructor 對象的 newInstance 方法。

demo:

public class TestReObject {
    private int id;
    private String name;
  
		public TestReObject(){
    }
    public TestReObject(int id,String name){
        this.id = id;
        this.name = name;
    }
}
String classString = "reflect.TestReObject";
Class cla = Class.forName(classString);
TestReObject reObject = (TestReObject) cla.newInstance();

Constructor constructor = cla.getConstructor(int.class,String.class);
TestReObject str2 = (TestReObject) constructor.newInstance(12,"abc");

PS

demo

public class AboutReflect {
    public static void main(String[] args) {
        try {
            //獲取class對象
            Class cla = Class.forName("Base.ObjectTest");




            //class對象創建實例對象方式一
            ObjectTest objectTest = (ObjectTest) cla.newInstance();

            //class對象創建實例對象方式二
            Constructor constructor = cla.getConstructor(int.class, String.class);
            ObjectTest objectTest1 = (ObjectTest) constructor.newInstance(12, "abc");





            //獲取 constructor數組及指定constructor
            Constructor[] constructors = cla.getConstructors();

            Constructor constructor0 = cla.getConstructor();
            Constructor constructor1 = cla.getConstructor(int.class,String.class);
            //可以獲取非public的構造函數
            Constructor constructor2 = cla.getDeclaredConstructor(int.class);
            System.out.println(constructor2.getParameterCount());

            for(Constructor cons:constructors){
                System.out.println(cons.getParameterCount());
            }





            //獲取屬性
            Field[] fields = cla.getFields();
            System.out.println("field數量:"+fields.length);

            //獲取屬性的註解,拿到超級權限,然後注入到指定對象
            Field fieldId = cla.getDeclaredField("id");
            fieldId.setAccessible(true);
            fieldId.set(objectTest,fieldId.getAnnotation(TestAnnotation.class).id());

            System.out.println(objectTest.toString());




            //獲取方法 並使用指定對象訪問
            Method method = cla.getDeclaredMethod("print",int.class,String.class);
            method.invoke(objectTest,996,"icu");
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}


class ObjectTest {
    @TestAnnotation(id=123)
    private long id;
    private String name;

    public ObjectTest() {
    }

    public ObjectTest(int id, String name) {
        this.id = id;
        this.name = name;
    }

    protected ObjectTest(int id){
        this.id = id;
    }

    public void print(int id,String name){
        System.out.println(id+"==="+name);
    }

    @Override
    public String toString() {
        return "ObjectTest{" +
                "id=" + id +
                ", name='" + name + '\'' +
                '}';
    }
}


@Retention(RetentionPolicy.RUNTIME)
@interface TestAnnotation {

    int id() default 1;

}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章