Java反射機制詳解

反射

如何在運行期間查找對象和類信息

主要用兩種形式:java

  • 傳統的「RTTI」,他假定咱們已知編譯和運行期擁有全部類型。
  • Java反射機制,利用他可在運行期獨立查找類信息。

爲何不用RTTI,由於它有一個限制:類型必須是在編譯期間已知的。web

Java反射機制是在運行狀態中,對於任意一個類,都可以知道這個類的全部屬性和方法。對於一個對象,都可以調用它的任意方法和屬性。api

這種動態獲取信息以及動態調用對象的方法的功能稱爲Java語言的反射機制。svg


用反射的條件?

要想使用反射機制,就必需要先獲取該類的字節碼文件對象(.class),經過字節碼文件對象,就可以經過該類中的方法獲取到咱們想要的全部信息(方法、屬性、類名、父類、實現的全部接口等等)。spa

在運行期,一旦咱們想生成那個類的一個對象,用於執行程序的JVM首先會檢查那個類型的class對象是否已經載入。若還沒有載入,JVM就會查找同名的.class文件,並將其載入。code

每個類對應着一個字節碼文件也就對應着一個class類型的對象,也就是字節碼文件對象。xml


反射經常使用API

在反射中,要獲取一個類或調用一個類的方法,咱們首先須要獲取到該類的class對象。對象

1.獲取反射中的class對象

首先咱們介紹一下動態加載靜態加載繼承

動態加載:程序在運行時調用相應方法,即便其餘方法是錯誤的,程序依舊會執行。經過動態加載可讓程序的可延長性大大提高,對之後的維護和擴展有重要意義。接口

靜態加載:程序在編譯時執行。在執行過程當中加載全部可能執行到的程序。在這種加載方式下,只要加載中一個方法出錯,程序就不能運行。咱們通常寫程序默認的是靜態加載。

有三種方法:

  • 當知道該類的全路徑名時,可使用Class.forName(類名)
    • 動態加載,運行時,開始裝入類,並做類的靜態初始化。
    • 指定什麼類名就獲取什麼類字節碼文件對象。
    • 該方法含義是加載參數指定的類,而且初始化他。
  • Class clz = String.class只適合在編譯前就知道要操做的Class。
    • 靜態加載(編譯時已加載)
  • 經過類對象的獲取class對象obj.getClass()。
    • 靜態加載(編譯時已加載)

第一種有更好的擴展性,因此通常狀況下,第一種用的較多。


2.經過反射建立類對象

有兩種方式:

  • 經過Class對象的newInstance()方法

    • Class clz = Person.class;Person per = (Person)clz.newInstance();
  • 經過Constructor對象的newInstance()

    • 選擇無參構造方法構造對象:
    Class clz = Person.class;
    Constructor constructor = clz.getConstructor();
    Person per = (Person)constructor.newInstance();
    • 選擇帶參的構造方法來構造對象
    Class clz = Person.class;
    Constructor constructor = clz.getConstructor(String.class, int.class);
    Person per = (Person)constructor.newInstance("小明", 15);

3.經過反射獲取類屬性、方法、構造器

經過class對象的getFields()能夠獲取到class的非私有屬性。

經過class對象的getDeclaredFields()方法能夠獲取包括私有屬性在內的全部屬性。

經過class對象得getMethods獲取該類中的全部方法,包括繼承和實現的方法。

經過class對象得getDeclaredMethods獲取該類中的全部方法(包括私有方法),不包括包括繼承方法。

PS:私有方法和私有屬性不能直接訪問,由於權限不夠。不過仍是有辦法的。

  • method.setAccessible(true)

  • field.setAccessible(true)


4.經過反射調用私有方法

經過反射,咱們能夠調用其它類的私有方法。

import java.lang.reflect.Method;

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

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

        Method m = c.getDeclaredMethod("pow", new Class[]{ int.class });
        m.setAccessible(true);//修改訪問權限
        m.invoke(obj, 4);//調用方法
    }
}
相關文章
相關標籤/搜索