1. 程式人生 > >Java 反射(基礎)

Java 反射(基礎)

一、反射的概述

JAVA反射機制是在執行狀態中,對於任意一個類,都能夠知道這個類的所有屬性和方法;對於任意一個物件,都能夠呼叫它的任意一個方法和屬性;這種動態獲取的資訊以及動態呼叫物件的方法的功能稱為java語言的反射機制。

要想解剖一個類,必須先要獲取到該類的位元組碼檔案物件。而解剖使用的就是Class類中的方法.所以先要獲取到每一個位元組碼檔案對應的Class型別的物件.

例如:一個類有:成員變數、方法、構造方法、包等等資訊,利用反射技術可以對一個類進行解剖,把個個組成部分對映成一個個物件。

 

1、獲取Class物件

獲取類物件的三種方式,1已經可以建立實體類了,再用反射,多此一舉;2需要配置檔案支援;3通過全限定名獲取,一般常用

2獲取構造器

請注意圖中的修飾符和引數

@Test//獲取構造器
public void objTest3() {

    System.out.println("**********************************獲取所有構造器**********************************");
    Class<?> aClass = null;
    try {
        aClass = Class.forName("com.example.reflex.Student");
    } catch (ClassNotFoundException e) {
        e.printStackTrace();
    }
    Constructor<?>[] constructors = aClass.getConstructors();
    System.out.println("**********************************獲取所有公共構造器**********************************");
    for (Constructor<?> constructor : constructors) {

        System.out.println("構造器輸出 : " + constructor);
    }
    System.out.println("**********************************獲取所有構造器(包括私有,受保護的)**********************************");
    Constructor<?>[] declaredConstructors = aClass.getDeclaredConstructors();
    for (Constructor<?> declaredConstructor : declaredConstructors) {
        System.out.println("構造器輸出 : " + declaredConstructor);
    }

    System.out.println("**********************************獲取預設的構造器(公有無參)**********************************");
    Constructor<?> constructor = null;
    try {
        constructor = aClass.getConstructor(null);
    } catch (NoSuchMethodException e) {
        e.printStackTrace();
    }
    System.out.println("構造器輸出:" + constructor);
}

控制檯輸出結果

getConstructors 獲取所有公共的構造器;getDeclaredConstructors 獲取所有構造器,包括私有,受保護的

 

獲取私有構造器,並呼叫

@Test//獲取私有構造器並呼叫
public void objTest4() {

    Class<?> aClass = null;
    try {
        aClass = Class.forName("com.example.reflex.Student");
    } catch (ClassNotFoundException e) {
        e.printStackTrace();
    }
    Constructor<?> declaredConstructor = null;
    try {
        //反射獲取構造方法物件
       declaredConstructor = aClass.getDeclaredConstructor(int.class);//String.class char.class int.class
    } catch (NoSuchMethodException e) {
        e.printStackTrace();
    }
    System.out.println("構造方法:" + aClass);
    declaredConstructor.setAccessible(true);//開啟暴力訪問,忽略訪問修飾符
    try {
        //構造方法中新增屬性、返回T型別
        Object newInstance  = declaredConstructor.newInstance(18);
    } catch (InstantiationException e) {
        e.printStackTrace();
    } catch (IllegalAccessException e) {
        e.printStackTrace();
    } catch (InvocationTargetException e) {
        e.printStackTrace();
    }
}

控制檯輸出結果

 

getDeclaredConstructor(int.class) 指定獲取構造器,引數int

反射回的物件.setAccessible(true); 開啟暴力模式,忽略修飾符

3獲取成員變數

@Test//獲取成員變數
public void Fields() {

    Class<?> aClass = null;
    try {
        aClass = Class.forName("com.example.reflex.reflexOfEntity");
    } catch (ClassNotFoundException e) {
        e.printStackTrace();
    }
    Field[] fields = aClass.getFields();
    System.out.println("**********************************獲取公有成員變數**********************************");
    for (Field field : fields) {
        System.out.println("成員變數:" + field);
    }

    System.out.println("**********************************獲取所有成員變數(包括私有、受保護、預設的)**********************************");
    Field[] declaredFields = aClass.getDeclaredFields();
    for (Field declaredField : declaredFields) {
        System.out.println("成員變數:" + declaredField);
    }

}

控制檯輸出結果

注意修飾符和成員變數名稱

類物件.getFields 獲取所有公有的成員變數;  類物件.getDeclaredFields 獲取所有的成員變數,包括私有的,受保護的,預設的;

 

@Test//獲取私有成員變數並呼叫
public void Fields2() {

    System.out.println("**********************************獲取私有屬性並呼叫**********************************");
    Class<?> aClass = null;
    try {
        aClass = Class.forName("com.example.reflex.reflexOfEntity");
    } catch (ClassNotFoundException e) {
        e.printStackTrace();
    }
    Field[] declaredFields = aClass.getDeclaredFields();
    for (Field declaredField : declaredFields) {
        System.out.println("遍歷所有成員變數:" + declaredField);
    } //private java.lang.String com.example.reflex.reflexOfEntity.phoneNum 獲取到的私有成員變數
    Field phoneNum = null;
    try {
        phoneNum = aClass.getDeclaredField("phoneNum");
    } catch (NoSuchFieldException e) {
        e.printStackTrace();
    }
    System.out.println("輸出私有成員變數:" + phoneNum);
    //反射類物件
    Object newInstance = null;
    try {
        newInstance = aClass.getConstructor().newInstance();
    } catch (InstantiationException e) {
        e.printStackTrace();
    } catch (IllegalAccessException e) {
        e.printStackTrace();
    } catch (InvocationTargetException e) {
        e.printStackTrace();
    } catch (NoSuchMethodException e) {
        e.printStackTrace();
    }
    phoneNum.setAccessible(true);//開啟暴力模式,忽略修飾符
    try {
        phoneNum.set(newInstance,"222");
    } catch (IllegalAccessException e) {
        e.printStackTrace();
    }
    reflexOfEntity reflexOfEntity = (reflexOfEntity) newInstance;//獲取類例項化物件
    System.out.println("輸出物件,檢視phoneNum屬性:" + reflexOfEntity);
}

 

控制檯輸出

私有的成員變數 phoneNum 被賦值

類物件.getConstructor().newInstance(); 獲取類例項化物件

成員變數物件.set(類例項化物件,"222");

aClass.getDeclaredField("phoneNum"); aClass(類物件)phoneNum (成員變數名稱)

 

4獲取方法

 

@Test//獲取方法
public void testMethod() {

    //獲取類物件
    Class<?> aClass = null;
    try {
        aClass = Class.forName("com.example.reflex.reflexOfMethod");
    } catch (ClassNotFoundException e) {
        e.printStackTrace();
    }

    System.out.println("**********************************獲取所有共有方法**********************************");
    //獲取所有的共有方法
    Method[] methods = aClass.getMethods();
    for (Method method : methods) {

        System.out.println("共有方法:" + method);
    }

    System.out.println("**********************************獲取所有(自定義)方法(包括私有,預設,受保護的)**********************************");
    //獲取所有方法
    Method[] declaredMethods = aClass.getDeclaredMethods();
    for (Method declaredMethod : declaredMethods) {

        System.out.println("所有方法:" + declaredMethod);
    }
}

控制檯輸出

注意方法名,修飾符,包名

getMethods();獲取所有共有方法,包括Java內設方法 ; getDeclaredMethods()獲取所有自定義方法,包括私有的,受保護的,預設的;

 

@Test//獲取指定方法,並呼叫
public void testMethod2() {

    //獲取類物件
    Class<?> aClass = null;
    try {
        aClass = Class.forName("com.example.reflex.reflexOfMethod");
    } catch (ClassNotFoundException e) {
        e.printStackTrace();
    }
    System.out.println("獲取類物件:" + aClass);
    System.out.println("**********************************獲取所有(自定義)方法(包括私有,預設,受保護的)**********************************");
    //獲取自定義所有方法
    Method[] declaredMethods = aClass.getDeclaredMethods();
    for (Method declaredMethod : declaredMethods) {

        System.out.println("檢視方法:" + declaredMethod);
    }
    //public void com.example.reflex.reflexOfMethod.show1(java.lang.String)公有方法show1
    //private java.lang.String com.example.reflex.reflexOfMethod.show4(int)私有方法show4

    //呼叫指定方法
    Method show1 = null;
    try {
        show1 = aClass.getMethod("show1", String.class);
    } catch (NoSuchMethodException e) {
        e.printStackTrace();
    }
    System.out.println("獲得方法:" + show1);
    //獲取類例項化物件
    Object newInstance = null;
    try {
        newInstance = aClass.getConstructor().newInstance();
    } catch (InstantiationException e) {
        e.printStackTrace();
    } catch (IllegalAccessException e) {
        e.printStackTrace();
    } catch (InvocationTargetException e) {
        e.printStackTrace();
    } catch (NoSuchMethodException e) {
        e.printStackTrace();
    }
    Object chenyb = null;
    try {
        chenyb = show1.invoke(newInstance, "Chenyb");
    } catch (IllegalAccessException e) {
        e.printStackTrace();
    } catch (InvocationTargetException e) {
        e.printStackTrace();
    }

    System.out.println("呼叫方法show1,輸出返回值:" + chenyb);
    Method show4 = null;
    try {
        show4 = aClass.getDeclaredMethod("show4", int.class);
    } catch (NoSuchMethodException e) {
        e.printStackTrace();
    }
    System.out.println("獲得私有方法:" + show4);
    //呼叫類物件
    show4.setAccessible(true);//暴力呼叫,忽略修飾符
    Object invoke = null;
    try {
        invoke = show4.invoke(newInstance, 18);
    } catch (IllegalAccessException e) {
        e.printStackTrace();
    } catch (InvocationTargetException e) {
        e.printStackTrace();
    }
    System.out.println("呼叫方法show4,輸出返回值:" + invoke);
}

 

控制檯輸出

-

以上環節,注意開啟暴力許可權的步奏,和引數型別  型別 型別 

2018-09-05

Chenyb 隨筆記錄,方便自己學習(學習到了Java 執行緒&反射,才感覺自己java 才剛剛入門)