反射

說到反射,相信有過編程經驗的人都不會陌生。反射機制讓Java變得更加的靈活。反射機制在Java的衆多特性中是很是重要的一個。下面就讓咱們一點一點了解它是怎麼一回事。


什麼是反射

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


反射有什麼用

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

2,在運行時構造任意一個類的對象;

3,在運行時判斷任意一個類所具備的成員變量和方法;

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

5,生成動態代理。


反射的API

學習一門語言,一種比較好的方式就是看它的API文檔,由於它的API是最權威的,最準確的。下面咱們一塊兒看看JDK的API對於反射是如何描述的吧!


與反射有關的全部接口以及類都在java.lang.reflect包裏。


接口

接口摘要

AnnotatedElement
    

表示目前正在此 VM 中運行的程序的一個已註釋元素。

GenericArrayType
    

GenericArrayType 表示一種數組類型,其組件類型爲參數化類型或類型變量。

GenericDeclaration
    

聲明類型變量的全部實體的公共接口。

InvocationHandler
    

InvocationHandler 是代理實例的調用處理程序 實現的接口。

Member
    

成員是一種接口,反映有關單個成員(字段或方法)或構造方法的標識信息。

ParameterizedType
    

ParameterizedType 表示參數化類型,如 Collection<String>。

Type
    

Type 是 Java 編程語言中全部類型的公共高級接口。

TypeVariable<D extends GenericDeclaration>
    

TypeVariable 是各類類型變量的公共高級接口。

WildcardType
    

WildcardType 表示一個通配符類型表達式,如 ?、? extends Number 或 ? super Integer。




類摘要

AccessibleObject
    

AccessibleObject 類是 Field、Method 和 Constructor 對象的基類。

Array
    

Array 類提供了動態建立和訪問 Java 數組的方法。

Constructor<T>
    

Constructor 提供關於類的單個構造方法的信息以及對它的訪問權限。

Field
    

Field 提供有關類或接口的單個字段的信息,以及對它的動態訪問權限。

Method
    

Method 提供關於類或接口上單獨某個方法(以及如何訪問該方法)的信息。

Modifier
    

Modifier 類提供了 static 方法和常量,對類和成員訪問修飾符進行解碼。

Proxy
    

Proxy 提供用於建立動態代理類和實例的靜態方法,它仍是由這些方法建立的全部動態代理類的超類。

ReflectPermission
    

反射操做的 Permission 類。


下面給你們寫了一個小實例:

[java] view plaincopy在CODE上查看代碼片派生到個人代碼片

    package reflection;  
      
    public class UserInfo {  
          
        private Integer id;  
        private String userName;  
        private String password;  
        public Integer getId() {  
            return id;  
        }  
        public void setId(Integer id) {  
            this.id = id;  
        }  
        public String getUserName() {  
            return userName;  
        }  
        public void setUserName(String userName) {  
            this.userName = userName;  
        }  
        public String getPassword() {  
            return password;  
        }  
        public void setPassword(String password) {  
            this.password = password;  
        }  
          
        @Override  
        public String toString(){  
            return this.getClass().getName();  
        }  
          
    }  



[java] view plaincopy在CODE上查看代碼片派生到個人代碼片

    package reflection;  
      
    public class GetClass {  
      
        public boolean ClassCheck(){  
            try {  
                  
                System.out.println("第一種,經過類自己得到對象");  
                Class UserClass = this.getClass();  
                System.out.println("第一種方式成功!類名:"+UserClass.toString()+"\n");  
                  
                System.out.println("第二種,經過子類實例獲取父類");  
                UserInfo ui = new UserInfo();  
                UserClass = ui.getClass();  
                Class SubUserClass = UserClass.getSuperclass();  
                System.out.println("第二種方式成功!類名:"+SubUserClass.toString()+"\n");  
                  
                System.out.println("第三種,經過類名加.class得到對象");  
                Class ForClass = reflection.UserInfo.class;  
                System.out.println("第三種方式成功!類名:"+ForClass.toString()+"\n");  
                  
                System.out.println("第四種,經過類名的字符串得到對象");  
                Class ForName = Class.forName("reflection.UserInfo");  
                System.out.println("第四種方式成功!類名:"+ForName.toString()+"\n");  
                  
            } catch (Exception e) {  
                e.printStackTrace();  
                return false;  
            }  
            return true;  
        }  
          
        @Override  
        public String toString(){  
            return this.getClass().getName();  
        }  
          
        public static void main(String[] args) {  
            GetClass gc = new GetClass();  
            gc.ClassCheck();  
            if (gc.ClassCheck()) {  
                System.out.println("全部反射所有成功!");  
            }  
            else {  
                System.out.println("反射有問題,請檢查!");  
            }  
        }  
      
    }  


向你們介紹了什麼是Java的反射機制,以及Java的反射機制有什麼用。上一篇比較偏重理論,理論的東西給人講出來總感受虛無縹緲,仍是結合一些實例比較形象具體。那麼今天就結合更多的實例具體說說。


實例一:得到完整的類名

[java] view plaincopy在CODE上查看代碼片派生到個人代碼片

    package reflection.getclassname;  
      
    //得到完整的類名  
    public class GetClassName {  
      
        public String getNameByClass() {  
              
            String name = "";  
            System.out.println("經過類自己得到對象");  
            Class UserClass = this.getClass();  
            System.out.println("得到對象成功!\n");  
              
            System.out.println("經過類對象得到類名");  
            name = UserClass.getName();  
            System.out.println("得到類名成功!");  
            return name;  
        }  
        public static void main(String[] args) {  
              
            GetClassName gcn = new GetClassName();  
            System.out.println("類名爲:"+gcn.getNameByClass());  
        }  
      
    }  


運行結果:

經過類自己得到對象
得到對象成功!

經過類對象得到類名
得到類名成功!
類名爲:reflection.getclassname.GetClass Name       


實例二:得到類的屬性

[java] view plaincopy在CODE上查看代碼片派生到個人代碼片

    package reflection.getfields;  
      
    import java.lang.reflect.Field;  
      
    //得到類的屬性  
    public class GetFields {  
      
        public static void getFieldNames(String className) {  
              
            try {  
                //得到類名  
                Class c = Class.forName(className);  
                //得到全部屬性  
                Field[] fds = c.getFields();  
                  
                for (int i=0; i<fds.length; i++)  
                {  
                    String fn = fds[i].getName();  
                    Class tc = fds[i].getType();  
                    String ft = tc.getName();  
                    System.out.println("該屬性的名字爲:"+fn+",該屬性的類型爲:"+ft);  
                }  
            }catch (Exception e) {  
                e.printStackTrace();  
            }  
        }  
          
        public static void main(String[] args) {  
            GetFields.getFieldNames("reflection.getfields.FieldInfo");  
        }  
      
    }  


運行結果:

該屬性的名字爲:id,該屬性的類型爲:java.lang.String

該屬性的名字爲:username,該屬性的類型爲:java.lang.String    


實例三:得到類實現的接口

[java] view plaincopy在CODE上查看代碼片派生到個人代碼片

    package reflection.getinterfaces;  
      
    //得到類實現的接口  
    public class GetInterfaces {  
      
        public static void getInterfaces(String className) {  
            try {  
                //取得類  
                Class cl = Class.forName(className);  
                Class[] ifs = cl.getInterfaces();  
                for (int i = 0; i<ifs.length;i++)  
                {  
                    String IName = ifs[i].getName();  
                    System.out.println("該類實現的接口名字爲:"+IName);  
                }  
            }catch (Exception e) {  
                e.printStackTrace();  
            }  
        }  
          
        public static void main(String[] args) {  
            GetInterfaces.getInterfaces("reflection.getinterfaces.Student");  
        }  
      
    }  


運行結果:

該類實現的接口名字爲:reflection.getinterfaces.Person    


實例四:得到類及其屬性的修飾符

[java] view plaincopy在CODE上查看代碼片派生到個人代碼片

    package reflection.getmodifiers;  
      
    import java.lang.reflect.Field;  
    import java.lang.reflect.Modifier;  
      
    import reflection.UserInfo;  
      
    //得到類及其屬性的修飾符  
    public class GetModifiers {  
      
        private String username = "liu shui jing";  
        float f = Float.parseFloat("1.000");  
        public static final int i = 37;  
          
        //得到類的修飾符  
        public static String useModifiers(UserInfo ui) {  
              
            Class uiClass = ui.getClass();  
            int m = uiClass.getModifiers();  
            return Modifier.toString(m);  
              
        }  
          
        //得到本類屬性的修飾符  
        public void checkThisClassModifiers() {  
              
            Class tc = this.getClass();       
            Field fl[] = tc.getDeclaredFields();  
          
            for(int i=0;i<fl.length;i++)  
            {  
                System.out.println("第"+(i+1)+"個屬性的修飾符爲:"+Modifier.toString(fl[i].getModifiers()));  
            }  
              
        }  
        public static void main(String[] args) {  
              
            //得到類的修飾符  
            UserInfo ui =new UserInfo();  
            System.out.println("得到這個類的修飾符:"+GetModifiers.useModifiers(ui)+"\n");  
              
            //得到本類屬性的修飾符  
            GetModifiers gm = new GetModifiers();  
            gm.checkThisClassModifiers();  
              
        }  
      
    }  

運行結果:

得到這個類的修飾符:public

 

第1個屬性的修飾符爲:private

第2個屬性的修飾符爲:

第3個屬性的修飾符爲:public static final      



實例五:得到類的構造函數

[java] view plaincopy在CODE上查看代碼片派生到個人代碼片

    package reflection.getconstructor;  
      
    import java.lang.reflect.Constructor;  
      
    //得到類的構造函數  
    public class GetConstructor {  
      
        //構造函數一  
        GetConstructor(int a) {  
              
        }  
          
        //構造函數二  
        GetConstructor(int a, String b) {  
              
        }  
          
        public static void getConstructorInfo(String className) {  
            try {  
                //得到類的對象  
                Class cl =Class.forName(className);  
                System.out.println("得到類"+className+"全部的構造函數");  
                Constructor ctorlist[] = cl.getDeclaredConstructors();  
                System.out.println("遍歷構造函數\n");  
                for(int i =0 ; i<ctorlist.length; i++)  
                {  
                    Constructor con = ctorlist[i];  
                    System.out.println("這個構造函數的名字爲:"+con.getName());  
                    System.out.println("經過構造函數得到這個類的名字爲:"+con.getDeclaringClass());  
                      
                    Class cp[] = con.getParameterTypes();  
                    for (int j=0; j<cp.length; j++)  
                    {  
                        System.out.println("參數 "+j+" 爲 "+cp[j]+"\n");  
                    }  
                }  
            }catch (Exception e) {  
                    System.err.println(e);            
            }  
        }  
        public static void main(String[] args) {  
            GetConstructor.getConstructorInfo("reflection.getconstructor.GetConstructor");  
        }  
      
    }  


運行結果:

得到類reflection.getconstructor.GetConstructor全部的構造函數

遍歷構造函數

 

這個構造函數的名字爲:reflection.getconstructor.GetConstructor

經過構造函數得到這個類的名字爲:class reflection.getconstructor.GetConstructor       

參數 0 爲 int

 

這個構造函數的名字爲:reflection.getconstructor.GetConstructor

經過構造函數得到這個類的名字爲:class reflection.getconstructor.GetConstructor

參數 0 爲 int

 

參數 1 爲 class java.lang.String


實例六:得到父類

[java] view plaincopy在CODE上查看代碼片派生到個人代碼片

    package reflection.getparentclass;  
      
    //得到父類  
    public class GetParentClass {  
      
        public static String getParentClass(UserInfoMore uim) {  
              
            //得到父類  
            Class uimc = uim.getClass().getSuperclass();  
            System.out.println("得到父類的名字爲:"+uimc.getName());  
            return uimc.getName();  
              
        }  
          
        public static void searchParentClass() {  
              
        }  
          
        public static void main(String[] args) {  
              
            UserInfoMore uim = new UserInfoMore();  
            System.out.println("成功得到UserInfoMore的父類:"+GetParentClass.getParentClass(uim));  
              
        }  
      
    }  


運行結果:

得到父類的名字爲:reflection.UserInfo

成功得到UserInfoMore的父類:reflection.UserInfo   


實例七:得到類的方法

[java] view plaincopy在CODE上查看代碼片派生到個人代碼片

    package reflection.getmethod;  
      
    import java.lang.reflect.Method;  
      
    //得到類的方法  
    public class GetMethod {  
      
        public static void getMethods(String className) {  
            try {  
                System.out.println("開始遍歷類"+className+".class");  
                //得到類名  
                Class cls = Class.forName(className);  
                //利用方法得到全部該類的方法  
                System.out.println("利用類的getDeclaredMethods得到類的全部方法");  
                Method ml[] =cls.getDeclaredMethods();  
                System.out.println("遍歷得到的方法數組\n");  
                for (int i = 0 ;i<ml.length;i++)  
                {  
                    System.out.println("開始遍歷第"+(i+1)+"個方法");  
                    Method m = ml[i];  
                    System.out.println("開始獲取方法的變量類型");  
                    Class ptype[] = m.getParameterTypes();  
                    for (int j=0; j<ptype.length; j++)  
                    {  
                        System.out.println("方法參數"+j+"類型爲"+ptype[j]);  
                    }  
                    Class gEx[] = m.getExceptionTypes();  
                    for (int j=0 ; j<gEx.length; j++)  
                    {  
                        System.out.println("異常"+j+"爲"+ gEx[j]);  
                    }  
                      
                    System.out.println("該方法的返回值類型爲:"+m.getReturnType()+"\n");  
                      
                }  
            }catch (Exception e) {  
                e.printStackTrace();  
            }  
        }  
          
        public static void main(String[] args) {  
            GetMethod.getMethods("reflection.UserInfo");  
        }  
      
    }  


運行結果:

開始遍歷類reflection.UserInfo.class

利用類的getDeclaredMethods得到類的全部方法         

遍歷得到的方法數組

 

開始遍歷第1個方法

開始獲取方法的變量類型

該方法的返回值類型爲:class java.lang.String

 

開始遍歷第2個方法

開始獲取方法的變量類型

該方法的返回值類型爲:class java.lang.Integer

 

開始遍歷第3個方法

開始獲取方法的變量類型

方法參數0類型爲class java.lang.String

該方法的返回值類型爲:void

 

開始遍歷第4個方法

開始獲取方法的變量類型

該方法的返回值類型爲:class java.lang.String

 

開始遍歷第5個方法

開始獲取方法的變量類型

方法參數0類型爲class java.lang.Integer

該方法的返回值類型爲:void

 

開始遍歷第6個方法

開始獲取方法的變量類型

該方法的返回值類型爲:class java.lang.String

 

開始遍歷第7個方法

開始獲取方法的變量類型

方法參數0類型爲class java.lang.String

該方法的返回值類型爲:void

 

java

相關文章
相關標籤/搜索