Java反射基本操作

一、定義

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

    JAVA有着一個非常突出的動態相關機制:Reflection,用在Java身上指的是我們可以於運行時加載、探知、使用編譯期間完全未知的classes。換句話說,Java程序可以加載一個運行時才得知名稱的class,獲悉其完整構造(但不包括methods定義),並生成其對象實體、或對其fields設值、或喚起其methods。

    在面向對象的世界裏萬事萬物皆對象,類也是對象,是java.lang.Class的實例對象。我們創建一個類的實例對象可以通過new關鍵字創建比如:User user = new User()。new對象是靜態加載類,在編譯時刻就得加載所有可能使用的類,當我們不想在編譯時刻加載所有的類,而是在運行時候需要哪個就動態的加載哪個比如:Class.froName(“類的全稱”)。

二、用法

(一) 場景

    1.在運行時判斷任意一個對象所屬的類。

    2.在運行時構造任意一個類的對象。

    3.在運行時判斷任意一個類所具有的成員變量和方法。

    4.在運行時調用任意一個對象的方法。

    5.生成動態代理。

    6.獲取泛型信息。

    7.獲取註解信息。

    8.獲取配置文件信息。

(二) 如何使用

    1. Class對象的獲取(類類型,描述其他類所具有的這些特性)。

try{       
    // 類的.class(最安全/性能最好)屬性(不會自動初始化該Class對象),任何一個類都一個隱含的靜態成員變量  
    Class c1 = User.class;  
  
    // 已知該類的對象通過getClass方法  
    Class c2 = user.getClass();  
  
    // 運用Class.forName(String className)動態加載類,className需要是類的全限定名(最常用)。
    Class c3 = Class.forName(“business.User”);    
  
    // 我們完全可以通過類的類類型(一個類只有一個類類型)創建該類的實例對象  
    User user = (User)c1.newInstance()  
  
}catch(ClassNotFoundExpcetion e){   
    e.printStackTrace();   
}  

    2.從Class類獲取信息(Class類提供了大量的實例方法來獲取該Class對象所對應的詳細信息,Class類大致包含如下方法,其中每個方法都包含多個重載版本) 。

     1)Constructor<T>getConstructor(Class<?>... parameterTypes)。

     2)Method getMethod(String name,Class<?>... parameterTypes)。

     3)Field getField(String name)。

     4)Method Constructor Field這些類都實現了java.lang.reflect.Member接口,程序可以通過Method對象來執行相應的方法,通過Constructor對象來調用對應的構造器創建實例,通過Filed對象直接訪問和修改對象的成員變量值。

    3.創建對象

      1)使用Class對象的newInstance()方法來創建該Class對象對應類的實例(這種方式要求該Class對象的對應類有默認構造器)。

      2)先使用Class對象獲取指定的Constructor對象, 再調用Constructor對象的newInstance()方法來創建該Class對象對應類的實例(通過這種方式可以選擇指定的構造器來創建實例)。

    4.訪問成員變量

      1)通過Class對象的的getField()方法可以獲取該類所包含的全部或指定的成員變量Field,Filed提供瞭如下兩組方法來讀取和設置成員變量值。

       PS:getDeclaredXxx方法可以獲取所有的成員變量,無論private/protected。

      2)getXxx(Objectobj): 獲取obj對象的該成員變量的值,此處的Xxx對應8中基本類型,如果該成員變量的類型是引用類型,則取消get後面的Xxx。

      3)setXxx(Objectobj, Xxx val): 將obj對象的該成員變量值設置成val值.此處的Xxx對應8種基本類型,如果該成員類型是引用類型,則取消set後面的Xxx。

    5.調用方法

      1)當獲取到某個類對應的Class對象之後,就可以通過該Class對象的getMethod來獲取一個Method數組或Method對象,每個Method對象對應一個方法,在獲得Method對象之後,就可以通過調用invoke方法來調用該Method對象對應的方法。

public class MethodDemo1(){  
    public static void main(String[] args){  
        // 要獲取print方法就是獲取類的信息,要先獲取類的類類型  
        A a1 = new A();  
        Class c = a1.getClass();  
        /* 
         *獲取方法由方法名和參數決定 
         *getMethod獲取的是public方法 
         *getDeclaredMethod自己聲明的方法 
         */  
        try{      
             //Method m = c.getMethod(“print”, new Class[]{int.class, int.class});  
             Method m = c.getMethod(“print”, int.class, int.class);  
  
             // 方法的反射操作是作用於m對象來進行方法的調用達到和a1.print調用的效果相同   
             // a1.print(10,10); 
             // 如果方法有參數則放回具體參數,沒有則放null  
             Object o = m.invoke(a1, 10, 10);  // 輸出20
  
        } catch (Exception e){  
            e.printStackTrace();    
        }  
    }  
}  
  
class A(){  
    public void print(int a, int b){  
        System.out.println(a+b);  
    }  
  
    public void print(String a, String b){  
        System.out.println(a.toUpperCase()+”,”+b.toLowerCase());  
    }  
}  

三、Java反射了解集合泛型的本質

 

public class MethodDemo2(){  
    public static void main(String[] args){  
        ArrayList list = new ArrayList();  
        ArrayList<String> list1 = new ArrayList<String>();  
  
        Class c1 = list.getClass();  
        Class c2 = list.getClass();  
        System.out.printlf(c1 == c2);  
        //反射的操作都是在編譯以後  
   
        /* 
         *返回結果爲true則說明編譯以後集合的泛型是去泛型化的; 
         *集合的泛型是爲了防止輸入錯誤,java的泛型只在編譯階段有效,編譯以後無效                         
         */  
        try{  
            Method e = c2.getMethod(“add”,Object.class);  
            e.invoke(list1,10);  
            System.out.println(list1.size());  
            //會發現,size=1說明此時泛型失效了,並且注意list1此時不能用for循環遍歷  
  
        }catch(Exception e){  
            e.printStackTrace();  
        }  
    }  
}  

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