Spring預熱之Java反射

概述

Java反射機制:在運行狀態中,能夠知道任意類的所有屬性和方法,能夠調用任意對象的所有屬性和方法

和"反"對應的就是"正",所謂的"正"就是指我們正常new出一個對象進行相應操作。那麼如果我們不知道要使用的類是什麼怎麼辦?比如JDBC中加載不同的數據庫驅動程序、Spring框架中注入各種Bean,同一個業務要操作很多不同的類,沒辦法把所有的對象new出來,這時候就要使用反射創建一個實例,然後再操作

常用操作

先寫一個類

public class Student {
    @Getter
    @Setter
    private String name;
    @Getter
    @Setter
    private int id;

    public Student() {
        System.out.println("無參構造器");
    }

    private Student(String name) {
        this.name = name;
        System.out.println("name:" + name);
    }

    public Student(String name, int id) {
        this.name = name;
        this.id = id;
        System.out.println("name:" + name + "id" + id);
    }
    private void eat(String name) {
        System.out.println(name + " eat chuanchuan");
    }

    public void study(){
        System.out.println("study");
    }
}

獲取Class對象

爲什麼要獲取Class對象呢?因爲所有的操作都是要先根據Class對象創建一個實例出來

  1. 使用Class.forName(“類全名”),因爲類可能不存在,所以會拋出ClassNotFoundException異常

    Class c1 = Class.forName(“java.lang.String”);
    
  2. 通過類名.Class獲取,最安全、性能最高,只適合在編譯前就知道要操作的類名的場景

    Class c1 = String.class
    
  3. 通過對象的getClass()獲取,適用於傳過來一個Object的對象,但是不知道具體是什麼類

    String str = new String("Hello");
    Class c3 = str.getClass();
    

創建對象

有兩種方法:

  1. 通過Class的newInstance()方法,只能使用無參構造方法

    Class<?> studentClass = Student.class;
    Student student = (Student) studentClass.newInstance();
    
  2. 通過Constructor對象的newInstance()方法,可以選擇構造方法,但是不能選擇私有構造方法,否則會報NoSuchMethodException異常

    Constructor<?> constructor1 = studentClass.getConstructor();
    Constructor<?> constructor2 = studentClass.getConstructor(String.class);
    Student s1 = (Student) constructor1.newInstance();
    Student s2 = (Student) constructor2.newInstance("zcs");
    

    最後一行代碼會報錯,因爲Student(String name)是私有的,那麼如何獲取私有的呢?看一下常用API

    方法名 作用
    getConstructors() 獲取public構造方法
    getDeclaredConstructors() 獲取所有構造方法
    getConstructor(Class<?>…) 獲取指定參數的public構造方法
    getDeclaredConstructor(Class<?>…) 獲取指定參數的構造方法(可以是private)

    把Constructor換成Field和Method就是對屬性和方法的操作,區別就是返回值不同

    例如Method method=class.getDeclaredMethod()

    還有就是對於獲取私有類型的方法(帶Declraed的),需要設置setAccessible(true),具體見下文

//        私有構造方法
        Constructor<?> constructor3 = studentClass.getDeclaredConstructor(String.class);
        constructor3.setAccessible(true);
        Student s3 = (Student) constructor3.newInstance("zcs");

//        私有屬性
        Field name = studentClass.getDeclaredField("name");
        name.setAccessible(true);
        System.out.println(name.get(s3));

//        私有方法,第一個參數是方法名,第二個是參數類型
        Method method = studentClass.getDeclaredMethod("eat",String.class);
        method.setAccessible(true);
//		 第一個參數是實例,第二個是具體參數
        method.invoke(s3,"zcs");
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章