1. 程式人生 > >Java 反射機制詳解(一)

Java 反射機制詳解(一)

Java 反射機制詳解(一)

主要介紹以下幾方面內容

  • 理解 Class 類
  • 理解 Java 的類載入機制
  • 學會使用 ClassLoader 進行類載入
  • 理解反射的機制
  • 掌握 Constructor、Method、Field 類的用法
  • 理解並掌握動態代理 

 1.Class類

通過Class類可以得到的資訊某個類的資料成員名、方法和構造器、某個類到底實現了哪些介面等,對於每個類而言,JRE 都為其保留一個不變的 Class 型別的物件,一個 Class 物件包含了特定某個類的有關資訊,Class 物件只能由系統建立物件 ,一個類在 JVM 中只會有一個Class例項,每個類的例項都會記得自己是由哪個 Class 例項所生成。

1.1 Class是什麼? 

答: Class是一個類

1.2 Class類封裝了什麼資訊?

答:封裝了當前物件所對應的類的資訊,包含類中的屬性,方法,構造器等

例如: 有一個Person類,一個Order類,一個Book類,這些都是不同的類,現在需要一個類,用來描述這些類,這就是Class類,它應該有類名,屬性,方法,構造器等。Class是用來描述類的類 Class類是一個物件照鏡子的結果,物件可以看到自己有哪些屬性,方法,構造器,實現了哪些介面等等

定義Person類: 

public class Person {

    String name;
    private int age;

    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public int getAge() {
        return age;
    }
    public void setAge(int age) {
        this.age = age;
    }
    
    // 帶參的構造器
    public Person(String name, int age) {
        super();
        this.name = name;
        this.age = age;
    }
    // 不帶參的構造器
    public Person() {
        super();
    }

 通過Class類獲取類物件:

public class ReflectionTest {
    @Test
    public void testClass() {
       Class clazz = null;
       
       //1.得到Class物件
       clazz = Person.class;
       
       System.out.println();  //插入斷點
    }
}

 在斷點處就可以看到Class對像包含的資訊:

 

 同樣,這些屬性值是可以獲取的:

public class ReflectionTest {
    @Test
    public void testClass() {
       Class clazz = null;
       
       //1.得到Class物件
       clazz = Person.class;
       //2.返回欄位的陣列
       Field[] fields = clazz.getDeclaredFields();
       
       System.out.println();  //插入斷點
    }
}

fields的內容如下:

 

 1.3 為什麼需要Class類物件?

a.有可能這個物件是別人傳過來的

b.有可能沒有物件,只有一個全類名

通過反射,可以得到這個類裡面的資訊

1.4 如何獲取Class物件? 

a.通過類名獲取      類名.class    

b.通過物件獲取      物件名.getClass()

c.通過全類名獲取    Class.forName(全類名)

public class ReflectionTest {
    @Test
    public void testClass() throws ClassNotFoundException {
       Class clazz = null;
       
       //1.通過類名
       clazz = Person.class;
       
       //2.通過物件名
       //這種方式是用在傳進來一個物件,卻不知道物件型別的時候使用
       Person person = new Person();
       clazz = person.getClass();
       //上面這個例子的意義不大,因為已經知道person型別是Person類,再這樣寫就沒有必要了
       //如果傳進來是一個Object類,這種做法就是應該的
       Object obj = new Person();
       clazz = obj.getClass();
       
       //3.通過全類名(會丟擲異常)
       //一般框架開發中這種用的比較多,因為配置檔案中一般配的都是全類名,通過這種方式可以得到Class例項
       String className=" com.atguigu.java.fanshe.Person";
       clazz = Class.forName(className);       
       
       //字串的例子
       clazz = String.class;
       
       clazz = "javaTest".getClass();
       
       clazz = Class.forName("java.lang.String");
       
       System.out.println(); 
    }
}

 1.5 Class類有哪些方法?

 

  • static Class forName(String name)    返回指定類名 name 的 Class 物件
  • Object newInstance()                        呼叫預設建構函式,返回該Class物件的一個例項
  • Object newInstance(Object []args)    呼叫當前格式建構函式,返回該Class物件的一個例項
  • getName()                                         返回此Class物件所表示的實體(類、介面、陣列類、基本型別或void)名稱
  • Class getSuperClass()                      返回當前Class物件的父類的Class物件
  • Class [] getInterfaces()                      獲取當前Class物件的介面
  • ClassLoader getClassLoader()         返回該類的類載入器
  • Class getSuperclass()                      返回表示此Class所表示的實體的超類的Class

 Class類的newInstance()方法 : 

public void testNewInstance() throws ClassNotFoundException, InstantiationException, IllegalAccessException{
        //1.獲取Class物件
        String className="com.atguigu.java.fanshe.Person";
        Class clazz = Class.forName(className);  
        
        //利用Class物件的newInstance方法建立一個類的例項
        Object obj =  clazz.newInstance();
        System.out.println(obj);
    }
    //結果是:[email protected]

可以看出確實是建立了一個Person例項,但是Person類有兩個構造方法,到底是呼叫的哪一個構造方法呢 

實際呼叫的是類的無引數的構造器。所以在我們在定義一個類的時候,定義一個有引數的構造器,作用是對屬性進行初始化,還要寫一個無引數的構造器,作用就是反射時候用 

一般地、一個類若宣告一個帶參的構造器,同時要宣告一個無引數的構造器

原文連結:https://www.cnblogs.com/tech-bird/p/3525336.html