Java基礎之反射機制(續)

weixin_34402408發表於2019-01-17

回顧

在上篇Java基礎之反射機制,講解了Class例項是反射的源頭,並且講解了獲取Class例項的三種方法:

  • 通過類名獲取
Class clazz= Person.class;
複製程式碼
  • 通過物件獲取
Person p=new Person();
Class clazz1=p.getClass();
複製程式碼
  • 通過Class類的靜態屬性
Class clazz3=Class.forName("com.zhang.Person");
 System.out.println(clazz3);
複製程式碼

那麼我們就可以利用這個Class例項做許多事情。

Class例項的使用

1.建立類的物件

String className="com.zhang.Person";
Class clazz= Class.forName(className);
Person person=(Person) clazz.newInstance();
複製程式碼

Person 類需要空參的構造器

空參構造器不能private修飾

2. 獲取類屬性

Class clazz= Person.class;
Field[] fields= clazz.getFields();//只能獲取執行時類及父類宣告為public的屬
for(int i=0;i<fields.length;i++){
  System.out.println(fields[i]);
}

 Field[] fields1 =clazz.getDeclaredFields();//獲取執行時類所有的屬性
for(Field f:fields1){
            System.out.println(f.getName());//獲取屬性名
            System.out.println(f.getModifiers());//獲取許可權修飾符
             int i= f.getModifiers();
            System.out.println(Modifier.toString(i));//轉化成對應值
        }
複製程式碼

3.獲取類方法

Class clazz= Person.class;
Method[] m1= clazz.getMethods();//獲取執行時類及其父類所有宣告為public的方法
for(Method m:m1){
  System.out.println(m);
}
Method[] m1=clazz.getDeclaredMethods();//獲取類本身宣告的所有方法
      for(Method m:m1){
          System.out.println(m);
           Annotation[] an= m.getAnnotations();//獲取註解
         for (Annotation a:an){
             System.out.println(a);
         }
          Class[] types= m.getParameterTypes();//獲得方法的引數型別
         for(Class type:types){
             System.out.println(type);
         }
         Class re =m.getReturnType();//獲得返回值型別
         System.out.println(re);
         
      Class[] es= m.getExceptionTypes();//獲得異常型別
       for(Class e :es){
           System.out.println(e);
       }
      }
複製程式碼

4.獲取構造方法

Class clazz= Person.class;
       Constructor[] cs= clazz.getConstructors();//獲得所有宣告的構造方法
       for (Constructor c:cs){
           System.out.println(c);
       }
複製程式碼

5.獲取父類

Class clazz= Person.class;
Class cs=clazz.getSuperclass();//獲取父類
Type type =clazz.getGenericSuperclass();//獲取帶泛型的父類
ParameterizedType param=(ParameterizedType)type;//獲取傳入父類的泛型
Type[] arg1=param.getActualTypeArguments();
System.out.println(((Class)arg1[0]).getName());

複製程式碼

6.獲取實現的介面

 Class[] in= clazz.getInterfaces();//獲取介面
for (Class i:in){
    System.out.println(i);
}
複製程式碼

7.獲取類所在的包

 Class clazz= Person.class;
System.out.println(clazz.getPackage());
複製程式碼

8.獲取類的註解

Class clazz= Person.class;
Annotation[] an=clazz.getAnnotations();
複製程式碼

利用反射呼叫執行時類中指定的方法和屬性

1.呼叫屬性

Class clazz= Person.class;
Field name=clazz.getField("name");//public許可權的
Person p=(Person) clazz.newInstance();
name.set(p,"hello");

 Field age=clazz.getDeclaredField("age");//獲取指定名屬性
age.setAccessible(true);//設定訪問許可權
age.set(p,12);
System.out.println(p);
複製程式碼

2.呼叫方法

 Class clazz= Person.class;
Person p=(Person) clazz.newInstance();//例項
Method m1= clazz.getMethod("show");//呼叫public修飾的方法
m1.invoke(p);//呼叫

  Class clazz= Person.class;
 Person p=(Person) clazz.newInstance();
  Method m1= clazz.getDeclaredMethod("display", String.class);//呼叫非public的指定方法
  m1.setAccessible(true);//設定許可權
  m1.invoke(p,"china");//呼叫

複製程式碼

3.呼叫靜態方法

Class clazz= Person.class;
Method m1= clazz.getMethod("show");
m1.invoke(Person.class);//呼叫靜態方法

複製程式碼

4.呼叫指定的構造器

 Class clazz= Person.class;
Constructor cons= clazz.getDeclaredConstructor(String.class,int.class);
cons.setAccessible(true);
Person p=(Person) cons.newInstance("lily",16);
System.out.println(p);
複製程式碼

總結

本篇首先介紹了利用Class例項如何獲取類完整的結構,包括屬性方法構造器註解和父類等等。然後接著介紹了具體利用反射我們如何呼叫指定的方法構造器和屬性。這樣整個反射的使用就打通了,下一篇講解反射的一個重要應用--動態代理。

喜歡本文的朋友們,歡迎長按下圖關注訂閱號"我的程式設計筆記",收看更多精彩內容~~

相關文章