反射,反射配置文件

 

1  Class類

JAVA反射機制是在運行狀態中,對於任意一個類,都能夠知道這個類的所有屬性和方法;對於任意一個對象,都能夠調用它的任意一個方法和屬性;這種動態獲取的信息以及動態調用對象的方法的功能稱爲java語言的反射機制。

1.1  獲取Class對象的三種方式:

複製代碼
public class Person {
    private String name;
    public int age;
    static{
        System.out.println("靜態代碼塊");
    }
    public     Person(){
        System.out.println("空參構造");
    }
    public Person(String name,int age){
        this.name=name;
        this.age=age;
        System.out.println("Person(String name,int age)");
    }
    private Person(String name){
        this.name=name;
        System.out.println("Person(String name)");
    }
    public void eat(){
        System.out.println("公共空參方法");
    }
    public void sleep(String name){
        System.out.println("公共有參方法");
    }
    public void smoke(){
        System.out.println("私有空參構造");
    }
    @Override
    public String toString() {
        return "Person [name=" + name + ", age=" + age + "]";
    }
}
複製代碼
複製代碼
public class Demo01 {
    public static void main(String[] args) throws ClassNotFoundException {
        //1.通過getClass方法獲取, 通過對象獲取
        Person p=new Person();
        Class c1=p.getClass();
        System.out.println(c1);
        //2.通過類名獲取
        Class c2=Person.class;
        System.out.println(c2);
        System.out.println(c1==c2);
        System.out.println(c1.equals(c2));
        //3.通過完整的包名+類名獲取
        Class c3=Class.forName("com.oracle.demo03.Person");
        System.out.println(c3);
    }
}
複製代碼

2     通過反射獲取構造方法並使用

在反射機制中,把類中的成員(構造方法、成員方法、成員變量)都封裝成了對應的類進行表示。其中,構造方法使用類Constructor表示。可通過Class類中提供的方法獲取構造方法:

複製代碼
public class Demo02 {
    //構造方法 Constructor
    //成員變量 Field
    //成員方法 Method
    public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, SecurityException, InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {
        //反射獲取構造方法
        //1.獲取Person.Class文件對象
        Class c=Class.forName("com.oracle.demo03.Person");
        //獲取所有公共的構造方法(數組)
        /*Constructor[]cons=c.getConstructors();
        //遍歷
        for(Constructor con:cons){
            System.out.println(con);
        }*/
        //獲取某個公共構造方法
        /*Constructor con1=c.getConstructor(String.class,int.class);
        System.out.println(con1);
        //通過構造方法創建對象
        Object obj=con1.newInstance("張三",18);
        System.out.println(obj);*/
        //獲取所有構造方法數組
        /*Constructor[]cons=c.getDeclaredConstructors();
        for(Constructor con:cons){
            System.out.println(con);
        }*/
        //獲取某個私有構造方法
        Constructor con=c.getDeclaredConstructor(String.class);
        //System.out.println(con);
        //暴力反射
        con.setAccessible(true);
        Object obj=con.newInstance("熊大");
        System.out.println(obj);
    }
}
複製代碼

3   通過反射獲取成員變量和成員方法並使用

在反射機制中,把類中的成員變量使用類Field表示。可通過Class類中提供的方法獲取成員變量:

在反射機制中,把類中的成員方法使用類Method表示。可通過Class類中提供的方法獲取成員方法:

複製代碼
public class Demo01 {
    public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException, SecurityException, IllegalArgumentException, IllegalAccessException, InvocationTargetException, NoSuchMethodException, InstantiationException {
        //獲取字節碼文件對象
        Class c=Class.forName("com.oracle.demo01.Person");
        //獲取所有的成員變量
        /*Field[]fields=c.getDeclaredFields();
        //遍歷
        for(Field field:fields){
            System.out.println(field);
        }*/
        //獲取某個成員變量並賦值
        /*Field field=c.getDeclaredField("age");
        Object obj=new Person();
        field.set(obj, 18);
        System.out.println(obj);*/
        //獲取所有成員方法
        /*Method[]methods=c.getDeclaredMethods();
        //遍歷
        for(Method method:methods){
            System.out.println(method);
        }*/
        //獲取單個成員方法
        Method method=c.getMethod("sleep", String.class);
        //調用方法
        Object obj=c.newInstance();    
        method.invoke(obj, "張三");
}

}

複製代碼

4  反射練習

4.1 泛型擦除

思考,將已存在的ArrayList<Integer>集合中添加一個字符串數據,如何實現呢?

其實程序編譯後產生的.class文件中是沒有泛型約束的,這種現象我們稱爲泛型的擦除。那麼,我們可以通過反射技術,來完成向有泛型約束的集合中,添加任意類型的元素

複製代碼
public class Demo02 {
    public static void main(String[] args) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException, NoSuchMethodException, SecurityException {
        //泛型擦除
        ArrayList<Integer>arr=new ArrayList<Integer>();
        //獲取ArrayList的字節碼文件對象
        Class c=arr.getClass();
        //通過反射的方式獲取add方法
        Method add=c.getMethod("add", Object.class);
        add.invoke(arr, "aaa");
        System.out.println(arr);
    }
}
複製代碼

4.2   反射配置文件

通過反射配置文件,運行配置文件中指定類的對應方法

讀取properties文件中的數據,通過反射技術,來完成Person對象的創建

複製代碼
public class Demo01 {
    public static void main(String[] args) throws IOException, ClassNotFoundException, InstantiationException, IllegalAccessException, NoSuchMethodException, SecurityException, IllegalArgumentException, InvocationTargetException {
        //明確配置文件的路徑
        FileReader fr=new FileReader("src/com/oracle/demo02/config.properties");
        //創建Properties集合
        Properties pro=new Properties();
        //從配置文件中讀取鍵值對到集合中
        pro.load(fr);
        //從集合中獲取完整的包名+類名
        String ClassName=pro.getProperty("ClassName");
        //獲取方法名
        String MethodName=pro.getProperty("MethodName");
        //通過反射獲取字節碼文件對象
        Class c=Class.forName(ClassName);
        //創建對象
        Object obj=c.newInstance();
        //獲取方法
        Method method=c.getMethod(MethodName);
        //調用方法
        method.invoke(obj);
    }
}
複製代碼

 

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