Java的反射

Adrian_Dai發表於2018-03-04

java.lang.Class類

java.lang.Class主要提供了以下兩個功能:

  1. 提供方法用於訪問執行期間類的後設資料;
  2. 提供方法用於檢查和修改類的執行時行為;

java.lang.Class類常用方法

MethodDescription
1) public String getName()返回類名
2) public static Class forName(String className)throws ClassNotFoundException載入類並返回Class物件
3) public Object newInstance()throws InstantiationException,IllegalAccessException建立例項物件
4) public boolean isInterface()判斷是否是介面
5) public boolean isArray()判斷是否是陣列
6) public boolean isPrimitive()判斷是否是原始資料型別
7) public Class getSuperclass()返回父類Class引用
8) public Field[] getDeclaredFields()throws SecurityException返回類的成員屬性欄位陣列
9) public Method[] getDeclaredMethods()throws SecurityException返回類的方法陣列
10) public Constructor[] getDeclaredConstructors()throws SecurityException返回類的構造方法陣列
11) public Method getDeclaredMethod(String name,Class[] parameterTypes)throws NoSuchMethodException,SecurityException
返回類中指定引數型別的方法

獲取Class物件的三種方式

有三種方式,如下:

  1. Class類的forName()方法,動態載入,執行時,開始裝入類, 並做類的靜態初始化
  2. 物件的getClass()方法,靜態載入(編譯時已載入)
  3. .class語法, 靜態載入(編譯時已載入)

通過反射建立物件

有兩種方式,如下:

  1. 通過Class物件的newInstance()方法建立,這種方式只能呼叫無參構造方法;
  2. 通過Constructor物件的newInstance()方法建立,這種方式適用於有參構造方法,並且還可以破壞單例模式,呼叫私有構造方法;

所以,通常來講,第二種方式比第一種使用範圍更廣


Class物件呼叫newInstance()方法示例
package dai;
class TestDai{}public class Test{ public static void main(String args[]) { try { Class<?> c = Class.forName("dai.TestDai"); TestDai td = (TestDai) c.newInstance(); } catch (Exception e) { System.out.println(e); } }}

Constructor物件呼叫newInstance()方法示例

注意這裡可以根據傳入引數的型別來得到指定的構造方法,還可以改變構造方法的訪問許可權限制。

package dai;

import java.lang.reflect.Constructor;

class TestDai{
    private String msg;
    void message()
    {
        System.out.println("Hello" + msg);
    }
    private Simple(String msg){
        this.msg = msg;
    }
}

public class Test
{
    public static void main(String args[])
    {
        try
        {
            Class<?> c = Class.forName("dai.TestDai");
            Constructor<?> con = c.getDeclaredConstructor(String.class);
            con.setAccessible(true);  //設定可訪問許可權的限制
            TestDai  td = (TestDai) con.newInstance("Java");
            td.message();
        }
        catch (Exception e)
        {
            System.out.println(e);
        }

    }
}




通過反射呼叫私有方法

通過反射,我們可以呼叫其它類的私有方法,主要涉及java.lang.Class和java.lang.reflect.Method類;

其中主要是用到了Method類的setAccessible方法和invoke方法,前者修改訪問許可權,後者呼叫方法

通過呼叫有參私有方法示例:

package dai;

import java.lang.reflect.Method;

class A
{
    private void message(int n)
    {
        System.out.println(n);
    }
}

class Test
{
    public static void main(String args[]) throws Exception
    {
        Class<A> a = A.class;
        Object obj = a.newInstance();

        Method m = a.getDeclaredMethod("message", new Class[]{ int.class });
        m.setAccessible(true);
        m.invoke(obj, 8);
    }
}

相關文章