Java反射機制詳解


 

java 反射 定義 功能 示例
概要:

Java反射機制詳解

| |目錄

  • 1反射機制是什么
  • 2反射機制能做什么
  • 3反射機制的相關API
  • ·通過一個對象獲得完整的包名和類名
  • ·實例化Class類對象
  • ·獲取一個對象的父類與實現的接口
  • ·獲取某個類中的全部構造函數 - 詳見下例
  • ·通過反射機制實例化一個類的對象
  • ·獲取某個類的全部屬性
  • ·獲取某個類的全部方法
  • ·通過反射機制調用某個類的方法
  • ·通過反射機制操作某個類的屬性
  • ·反射機制的動態代理
  • 4反射機制的應用實例
  • ·在泛型為Integer的ArrayList中存放一個String類型的對象。
  • ·通過反射取得並修改數組的信息
  • ·通過反射機制修改數組的大小
  • ·將反射機制應用於工廠模式

1反射機制是什么

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

2反射機制能做什么

反射機制主要提供了以下功能: 

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

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

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

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

  • 生成動態代理。

3反射機制的相關API

通過一個對象獲得完整的包名和類名

Java |  復制
1
2
3
4
5
6
7
8
package  net.xsoftlab.baike;
public  class  TestReflect {
     public  static  void  main(String[] args)  throws  Exception {
         TestReflect testReflect =  new  TestReflect();
         System.out.println(testReflect.getClass().getName());
          結果 net.xsoftlab.baike.TestReflect
     }
}

實例化Class類對象

Java |  復制
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
package  net.xsoftlab.baike;
public  class  TestReflect {
     public  static  void  main(String[] args)  throws  Exception {
         Class<?> class1 =  null ;
         Class<?> class2 =  null ;
         Class<?> class3 =  null ;
          一般采用這種形式
         class1 = Class.forName( "net.xsoftlab.baike.TestReflect" );
         class2 =  new  TestReflect().getClass();
         class3 = TestReflect. class ;
         System.out.println( "類名稱   "  + class1.getName());
         System.out.println( "類名稱   "  + class2.getName());
         System.out.println( "類名稱   "  + class3.getName());
     }
}

獲取一個對象的父類與實現的接口

Java |  復制
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
package  net.xsoftlab.baike;
import  java.io.Serializable;
public  class  TestReflect  implements  Serializable {
     private  static  final  long  serialVersionUID = -2862585049955236662L;
     public  static  void  main(String[] args)  throws  Exception {
         Class<?> clazz = Class.forName( "net.xsoftlab.baike.TestReflect" );
          取得父類
         Class<?> parentClass = clazz.getSuperclass();
         System.out.println( "clazz的父類為:"  + parentClass.getName());
          clazz的父類為: java.lang.Object
          獲取所有的接口
         Class<?> intes[] = clazz.getInterfaces();
         System.out.println( "clazz實現的接口有:" );
         for  ( int  i =  0 ; i < intes.length; i++) {
             System.out.println((i +  1 ) +  ":"  + intes[i].getName());
         }
          clazz實現的接口有:
          1:java.io.Serializable
     }
}

獲取某個類中的全部構造函數 - 詳見下例

通過反射機制實例化一個類的對象

Java |  復制
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
package  net.xsoftlab.baike;
import  java.lang.reflect.Constructor;
public  class  TestReflect {
     public  static  void  main(String[] args)  throws  Exception {
         Class<?> class1 =  null ;
         class1 = Class.forName( "net.xsoftlab.baike.User" );
          第一種方法,實例化默認構造方法,調用set賦值
         User user = (User) class1.newInstance();
         user.setAge( 20 );
         user.setName( "Rollen" );
         System.out.println(user);
          結果 User [age=20, name=Rollen]
          第二種方法 取得全部的構造函數 使用構造函數賦值
         Constructor<?> cons[] = class1.getConstructors();
          查看每個構造方法需要的參數
         for  ( int  i =  0 ; i < cons.length; i++) {
             Class<?> clazzs[] = cons[i].getParameterTypes();
             System.out.print( "cons["  + i +  "] (" );
             for  ( int  j =  0 ; j < clazzs.length; j++) {
                 if  (j == clazzs.length -  1 )
                     System.out.print(clazzs[j].getName());
                 else
                     System.out.print(clazzs[j].getName() +  "," );
             }
             System.out.println( ")" );
         }
          結果
          cons[0] (java.lang.String)
          cons[1] (int,java.lang.String)
          cons[2] ()
         user = (User) cons[ 0 ].newInstance( "Rollen" );
         System.out.println(user);
          結果 User [age=0, name=Rollen]
         user = (User) cons[ 1 ].newInstance( 20 "Rollen" );
         System.out.println(user);
          結果 User [age=20, name=Rollen]
     }
}
class  User {
     private  int  age;
     private  String name;
     public  User() {
         super ();
     }
     public  User(String name) {
         super ();
         this .name = name;
     }
     public  User( int  age, String name) {
         super ();
         this .age = age;
         this .name = name;
     }
     public  int  getAge() {
         return  age;
     }
     public  void  setAge( int  age) {
         this .age = age;
     }
     public  String getName() {
         return  name;
     }
     public  void  setName(String name) {
         this .name = name;
     }
     @Override
     public  String toString() {
         return  "User [age="  + age +  ", name="  + name +  "]" ;
     }
}

獲取某個類的全部屬性

Java |  復制
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
package  net.xsoftlab.baike;
import  java.io.Serializable;
import  java.lang.reflect.Field;
import  java.lang.reflect.Modifier;
public  class  TestReflect  implements  Serializable {
     private  static  final  long  serialVersionUID = -2862585049955236662L;
     public  static  void  main(String[] args)  throws  Exception {
         Class<?> clazz = Class.forName( "net.xsoftlab.baike.TestReflect" );
         System.out.println( "===============本類屬性===============" );
          取得本類的全部屬性
         Field[] field = clazz.getDeclaredFields();
         for  ( int  i =  0 ; i < field.length; i++) {
              權限修飾符
             int  mo = field[i].getModifiers();
             String priv = Modifier.toString(mo);
              屬性類型
             Class<?> type = field[i].getType();
             System.out.println(priv +  " "  + type.getName() +  " "  + field[i].getName() +  ";" );
         }
         
         System.out.println( "==========實現的接口或者父類的屬性==========" );
          取得實現的接口或者父類的屬性
         Field[] filed1 = clazz.getFields();
         for  ( int  j =  0 ; j < filed1.length; j++) {
              權限修飾符
             int  mo = filed1[j].getModifiers();
             String priv = Modifier.toString(mo);
              屬性類型
             Class<?> type = filed1[j].getType();
             System.out.println(priv +  " "  + type.getName() +  " "  + filed1[j].getName() +  ";" );
         }
     }
}

獲取某個類的全部方法

Java |  復制
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
package  net.xsoftlab.baike;
import  java.io.Serializable;
import  java.lang.reflect.Method;
import  java.lang.reflect.Modifier;
public  class  TestReflect  implements  Serializable {
     private  static  final  long  serialVersionUID = -2862585049955236662L;
     public  static  void  main(String[] args)  throws  Exception {
         Class<?> clazz = Class.forName( "net.xsoftlab.baike.TestReflect" );
         Method method[] = clazz.getMethods();
         for  ( int  i =  0 ; i < method.length; ++i) {
             Class<?> returnType = method[i].getReturnType();
             Class<?> para[] = method[i].getParameterTypes();
             int  temp = method[i].getModifiers();
             System.out.print(Modifier.toString(temp) +  " " );
             System.out.print(returnType.getName() +  "  " );
             System.out.print(method[i].getName() +  " " );
             System.out.print( "(" );
             for  ( int  j =  0 ; j < para.length; ++j) {
                 System.out.print(para[j].getName() +  " "  "arg"  + j);
                 if  (j < para.length -  1 ) {
                     System.out.print( "," );
                 }
             }
             Class<?> exce[] = method[i].getExceptionTypes();
             if  (exce.length >  0 ) {
                 System.out.print( ") throws " );
                 for  ( int  k =  0 ; k < exce.length; ++k) {
                     System.out.print(exce[k].getName() +  " " );
                     if  (k < exce.length -  1 ) {
                         System.out.print( "," );
                     }
                 }
             else  {
                 System.out.print( ")" );
             }
             System.out.println();
         }
     }
}

通過反射機制調用某個類的方法

Java |  復制
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
package  net.xsoftlab.baike;
import  java.lang.reflect.Method;
public  class  TestReflect {
     public  static  void  main(String[] args)  throws  Exception {
         Class<?> clazz = Class.forName( "net.xsoftlab.baike.TestReflect" );
          調用TestReflect類中的reflect1方法
         Method method = clazz.getMethod( "reflect1" );
         method.invoke(clazz.newInstance());
          Java 反射機制 - 調用某個類的方法1.
          調用TestReflect的reflect2方法
         method = clazz.getMethod( "reflect2" int . class , String. class );
         method.invoke(clazz.newInstance(),  20 "張三" );
          Java 反射機制 - 調用某個類的方法2.
          age -> 20. name -> 張三
     }
     public  void  reflect1() {
         System.out.println( "Java 反射機制 - 調用某個類的方法1." );
     }
     public  void  reflect2( int  age, String name) {
         System.out.println( "Java 反射機制 - 調用某個類的方法2." );
         System.out.println( "age -> "  + age +  ". name -> "  + name);
     }
}

通過反射機制操作某個類的屬性

Java |  復制
1
2
3
4
5
6
7
8
9
10
11
12
13
14
package  net.xsoftlab.baike;
import  java.lang.reflect.Field;
public  class  TestReflect {
     private  String proprety =  null ;
     public  static  void  main(String[] args)  throws  Exception {
         Class<?> clazz = Class.forName( "net.xsoftlab.baike.TestReflect" );
         Object obj = clazz.newInstance();
          可以直接對 private 的屬性賦值
         Field field = clazz.getDeclaredField( "proprety" );
         field.setAccessible( true );
         field.set(obj,  "Java反射機制" );
         System.out.println(field.get(obj));
     }
}

反射機制的動態代理

Java |  復制
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
 獲取類加載器的方法
TestReflect testReflect =  new  TestReflect();
         System.out.println( "類加載器  "  + testReflect.getClass().getClassLoader().getClass().getName());
package  net.xsoftlab.baike;
import  java.lang.reflect.InvocationHandler;
import  java.lang.reflect.Method;
import  java.lang.reflect.Proxy;
定義項目接口
interface  Subject {
     public  String say(String name,  int  age);
}
 定義真實項目
class  RealSubject  implements  Subject {
     public  String say(String name,  int  age) {
         return  name +  "  "  + age;
     }
}
class  MyInvocationHandler  implements  InvocationHandler {
     private  Object obj =  null ;
     public  Object bind(Object obj) {
         this .obj = obj;
         return  Proxy.newProxyInstance(obj.getClass().getClassLoader(), obj.getClass().getInterfaces(),  this );
     }
     public  Object invoke(Object proxy, Method method, Object[] args)  throws  Throwable {
         Object temp = method.invoke( this .obj, args);
         return  temp;
     }
}
/**
  * 在java中有三種類類加載器。
 
  * 1)Bootstrap ClassLoader 此加載器采用c++編寫,一般開發中很少見。
 
  * 2)Extension ClassLoader 用來進行擴展類的加載,一般對應的是jrelibext目錄中的類
 
  * 3)AppClassLoader 加載classpath指定的類,是最常用的加載器。同時也是java中默認的加載器。
 
  * 如果想要完成動態代理,首先需要定義一個InvocationHandler接口的子類,已完成代理的具體操作。
 
  * @author xsoftlab.net
 
  */
public  class  TestReflect {
     public  static  void  main(String[] args)  throws  Exception {
         MyInvocationHandler demo =  new  MyInvocationHandler();
         Subject sub = (Subject) demo.bind( new  RealSubject());
         String info = sub.say( "Rollen" 20 );
         System.out.println(info);
     }
}

4反射機制的應用實例

在泛型為Integer的ArrayList中存放一個String類型的對象。

Java |  復制
1
2
3
4
5
6
7
8
9
10
11
package  net.xsoftlab.baike;
import  java.lang.reflect.Method;
import  java.util.ArrayList;
public  class  TestReflect {
     public  static  void  main(String[] args)  throws  Exception {
         ArrayList<Integer> list =  new  ArrayList<Integer>();
         Method method = list.getClass().getMethod( "add" , Object. class );
         method.invoke(list,  "Java反射機制實例。" );
         System.out.println(list.get( 0 ));
     }
}

通過反射取得並修改數組的信息

Java |  復制
1
2
3
4
5
6
7
8
9
10
11
12
13
package  net.xsoftlab.baike;
import  java.lang.reflect.Array;
public  class  TestReflect {
     public  static  void  main(String[] args)  throws  Exception {
         int [] temp = {  1 2 3 4 5  };
         Class<?> demo = temp.getClass().getComponentType();
         System.out.println( "數組類型: "  + demo.getName());
         System.out.println( "數組長度  "  + Array.getLength(temp));
         System.out.println( "數組的第一個元素: "  + Array.get(temp,  0 ));
         Array.set(temp,  0 100 );
         System.out.println( "修改之后數組第一個元素為: "  + Array.get(temp,  0 ));
     }
}

通過反射機制修改數組的大小

Java |  復制
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
package  net.xsoftlab.baike;
import  java.lang.reflect.Array;
public  class  TestReflect {
     public  static  void  main(String[] args)  throws  Exception {
         int [] temp = {  1 2 3 4 5 6 7 8 9  };
         int [] newTemp = ( int []) arrayInc(temp,  15 );
         print(newTemp);
         String[] atr = {  "a" "b" "c"  };
         String[] str1 = (String[]) arrayInc(atr,  8 );
         print(str1);
     }
      修改數組大小
     public  static  Object arrayInc(Object obj,  int  len) {
         Class<?> arr = obj.getClass().getComponentType();
         Object newArr = Array.newInstance(arr, len);
         int  co = Array.getLength(obj);
         System.arraycopy(obj,  0 , newArr,  0 , co);
         return  newArr;
     }
      打印
     public  static  void  print(Object obj) {
         Class<?> c = obj.getClass();
         if  (!c.isArray()) {
             return ;
         }
         System.out.println( "數組長度為: "  + Array.getLength(obj));
         for  ( int  i =  0 ; i < Array.getLength(obj); i++) {
             System.out.print(Array.get(obj, i) +  " " );
         }
         System.out.println();
     }
}

將反射機制應用於工廠模式

Java |  復制
</
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
package  net.xsoftlab.baike;
interface  fruit {
     public  abstract  void  eat();
}
class  Apple  implements  fruit {
     public  void  eat() {
         System.out.println( "Apple" );
     }
}
class  Orange  implements  fruit {
     public  void  eat() {
         System.out.println( "Orange" );
     }
}
class  Factory {
     public  static  fruit getInstance(String ClassName) {
         fruit f =  null ;
         try  {
             f = (fruit) Class.forName(ClassName).newInstance();
         catch  (Exception e) {
             e.printStackTrace();
         }
         return  f;
     }
}
/**
  * 對於普通的工廠模式當我們在添加一個子類的時候,就需要對應的修改工廠類。 當我們添加很多的子類的時候,會很麻煩。
  * Java 工廠模式可以參考
  * http:baike.xsoftlab.net/view/java-factory-pattern
 
  * 現在我們利用反射機制實現工廠模式,可以在不修改工廠類的情況下添加任意多個子類。
 
  * 但是有一點仍然很麻煩,就是需要知道完整的包名和類名,這里可以使用properties配置文件來完成。
 
  * java 讀取 properties 配置文件 的方法可以參考
  * http:baike.xsoftlab.net/view/java-read-the-properties-configuration-file
 
  * @author xsoftlab.net
  */
public  class  TestReflect {
     public  static  void  main(String[] args)  throws  Exception {
         fruit f = Factory.getInstance( "net.xsoftlab.baike.Apple" );
         if  (f !=  null ) {
             f.eat();
         }
     }
}

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM