天天看點

學JAVA的第三天之反射

反射是什麼? 是指在程式運作期間,可以動态建立對象。

(1)獲得位元組碼檔案對象的三種方法

為什麼要擷取位元組碼檔案對象,隻有這樣,才能通過位元組碼檔案對象去建立類的對象,而不是用new,這樣友善了程式的修改。直接修改配置檔案,便可以更改建立的類。

1.Object類的getclass()方法:同一個類的位元組碼隻被加載一次

2.類.class:任何一個類在生成的.class檔案中,會産生一個Class對象,用于表示這個類的類型資訊

3.Class.forName(類名):注意類名的寫法應該是全路徑,包括包名

package demo;
public class test {
    public static void main(String[] args) throws ClassNotFoundException {
        //1.Object類的getclass()  通過同一個類建立的位元組碼檔案是一樣的,隻被加載一次
        Person p1 = new Person();
        Person p2 = new Person();
        Class class1= p1.getClass();
        Class class2= p2.getClass();
        System.out.println(class1);
        System.out.println(class2);
        System.out.println(class1==class2);
        //2.類名.class對象
        Class class3= Person.class;
        System.out.println(class2==class3);
        //3.類型名.forName()
        Class class4= Class.forName("demo.Person");//注意是包名.類名
        System.out.println(class3==class4);
        //結果是:
        class demo.Person
		class demo.Person
		true
		true
		true
           

(2)位元組碼檔案對象裡面有什麼

位元組碼檔案對象
構造方法 構造方法對象(類型為constructor)
成員變量 成員變量對象(類型為filed)
成員函數 成員函數對象(類型為method)

(3)用位元組碼檔案對象來建立一個類的對象

------------------------------------------------Person2.java
package demo;
public class Person2 {
        public Person2(){};//類的構造方法1
        public Person2(String name,int age){//類的構造方法2
            super();
            this.name=name;
            this.age=age;
        }
        private String name;
        private int age;
        public void eat(){
            System.out.println("吃吃吃222");
        }
    }
------------------------------------------------test.java
package demo;
public class test {
    public static void  main(String[] args) {
      	 // Person p=new Person(); 這是傳統的建立對象的方法
        //讀取配置檔案中類的資訊,想建立什麼類就建立什麼,可在外部配置檔案中修改
        FileReader f=new FileReader("aa.txt");
        BufferedReader br=new BufferedReader(f);
        String str=br.readLine();
        System.out.println(str);
        //--------------第一步:用Class.forName()來建立位元組碼檔案對象
        Class clazz=Class.forName(str); 
        //--------------第二步:擷取類中的構造器對象
        //獲得Person類的構造方法,用Constructor數組來存儲一共有幾個(隻能得到public的構造方法)
        Constructor[] constructors =clazz.getConstructors();
        System.out.println(constructors.length);
        System.out.println(constructors[0]);//輸出構造方法1
        System.out.println(constructors[1]);//輸出構造方法2
        //--------------第三步:選擇其中一個,用newInstance()來建立對象
        Constructor c=constructors[0];
		//傳回的是Object類型,再進行類型轉換
        Object obj=c.newInstance();
        //相當于建立了一個Person2類的對象 a ,不是以前傳統的用new建立的
        Person2 a=(Person2) obj;
        a.eat();
    }
}
//結果為:2
		public demo.Person2()
		public demo.Person2(java.lang.String,int)
		吃吃吃222
           

(4)得到位元組碼檔案對象中的成員方法對象Method

1.擷取位元組碼檔案對象

2.得到某個特定的方法 【要知道方法名+形參】

3.建立對象【調用的傳統方法是對象.方法(對象),但反射裡面是:方法.invoke(對象,實參)】

4.反射調用

package demo;

public class Person2 {
    Person2(String name){//類的構造方法3
        super();
        this.name=name;
    }
    private String name;
    public void setName(String name) {
        this.name = name;
       System.out.println(name);
    }
}
           
package demo;

//-----------------------得到位元組碼中的成員方法對象 Method
public class test2 {
    public static void main(String[] args) {
  	    //--------------第一步:得到位元組碼檔案對象
        Class clazz=Class.forName("demo.Person2");
        //Method[] methods= clazz.getMethods();//父類繼承下來的+自身的+public,才可以顯示出來
        //增強型的for循環。Method是元素類型,method是每一個元素變量,methods是你要周遊的數組
        //for(Method method:methods)
        //System.out.println(method);
         //--------------第二步:得到特定的方法 要知道方法名+形參。
        Method method=clazz.getMethod("setName",String.class);
        System.out.println(method);
        // Constructor constructor=clazz.getConstructor(); 傳統方法是用構造器去建立執行個體
        //Object newInstance=constructor.newInstance();
        //--------------第三步:建立方法所在類的對象,是更便捷的方法,但隻針對無參數
        Object newInstance=clazz.newInstance();
        //--------------第四步:反射調用
        Object a=method.invoke(newInstance,"haha");
    }
}
//結果是:public void demo.Person2.setName(java.lang.String)
haha