反射

一個類有多個組成部分,例如:成員變量,方法,構造方法等。反射就是加載類,並解剖(反射)出類的各個組成部分。
本人在下面的反射例子中以註釋的形式把所理解的東西寫了出來java

Person類:數組

 1 import java.util.List;
 2 
 3 public class Person {
 4 
 5     /*
 6      * 1.構造方法
 7      */
 8     //無參的
 9     public Person(){
10         System.out.println("無參的構造方法!");
11     }
12     //一個參數,類型爲String的
13     public Person(String name){
14         System.out.println("name:" + name);
15     }
16     //一個參數,類型爲int的,且爲私有的
17     private Person(int age){
18         System.out.println("age:" + age);
19     }
20     //參數爲兩個參數
21     public Person(String name, int age){
22         System.out.println(name + "的年齡:" + age + "歲");
23     }
24     //參數爲List的
25     public Person(List list){
26         System.out.println("list:" + list);
27     }
28     
29     /*
30      * 2.普通方法
31      */
32     //一、無參
33     public void methodTest(){
34         System.out.println("這是無參的普通方法!");
35     }
36     
37     //二、一個參數
38     public void methodTest(String name){
39         System.out.println("名字:" + name);
40     }
41     //三、一個參數私有的
42     private void methodTest(int age){
43         System.out.println("年齡:" + age);
44     }
45     //四、兩個參數靜態的
46     public static void methodTest(String name, int age){
47         System.out.println(name + "的年齡:" + age);
48     }
49     //五、main方法
50     public static void main(String[] args) {
51         System.out.println("main方法:");
52     }
53     
54     /*
55      * 3.字段
56      */
57     public String name = "張三";
58     private int age = 25;
59     private static String password = "PaSs1111";
60 }

測試代碼:函數

  1 import java.lang.reflect.Constructor;
  2 import java.lang.reflect.Field;
  3 import java.lang.reflect.InvocationTargetException;
  4 import java.lang.reflect.Method;
  5 import java.util.ArrayList;
  6 import java.util.List;
  7 
  8 import org.junit.Test;
  9 
 10 public class ReflectTest {
 11 
 12     /**
 13      * @功能:反射
 14      * @介紹:
 15      *         clazz1.getConstructor()中的參數是可變參數,
 16      *     且用clazz1.getConstructor()只能反射出public型的,private反射不到
 17      *     若是想要獲得private的構造方法,則須要用clazz.getDeclaredConstructor()來反射private的構造函數
 18      * @日期:2013-10-22
 19      */
 20 
 21     /*
 22      * 1.構造方法反射
 23      */
 24     @Test
 25     public void test1() throws Exception{
 26         //加載類(方式一) 參數中類名要全稱
 27         Class clazz1 = Class.forName("cn.itcast.reflect.Person");
 28         //加載類(方式二)  ==> 實例化的時候構造方法直接運行
 29 //        Class clazz2 = new Person().getClass();
 30         //加載類(方式三)
 31 //        Class clazz3 = Person.class;
 32         //反射無參的構造方法,null表示無參
 33         Constructor c = clazz1.getConstructor(null);
 34         //new一個對象(正常狀況下返回的是Object型的,這裏強轉爲Person)
 35         Person p = (Person) c.newInstance();
 36     }
 37     
 38     @Test
 39     public void test2() throws Exception{
 40         //加載類
 41         Class clazz = Class.forName("cn.itcast.reflect.Person");
 42         //解剖(反射)出參數爲String的構造方法(String.class)
 43         Constructor c = clazz.getConstructor(String.class);
 44         c.newInstance("張三");
 45     }
 46     
 47     @Test
 48     public void test3() throws Exception{
 49         //加載類
 50         Class clazz = Class.forName("cn.itcast.reflect.Person");
 51         //解剖(反射)出參數爲int的構造方法(int.class)
 52         /*
 53          * 由於此時的構造方法爲private的,因此正常的clazz.getConstructor(),不能反射出來
 54          * 此時就要用clazz.getDeclaredConstructor()來反射private的構造函數
 55          * 但解剖出來的構造方法不能直接new一個新的對象,還得能過c.setAccessible(true)修改一下屬性(暴力反射)
 56          * ,這時才能進行new新對象,和正常的反射同樣了
 57          */
 58         Constructor c = clazz.getDeclaredConstructor(int.class);
 59         //打開訪問權限
 60         c.setAccessible(true);
 61         c.newInstance(25);
 62     }
 63     
 64     @Test
 65     public void test4() throws Exception{
 66         //加載類
 67         Class clazz = Class.forName("cn.itcast.reflect.Person");
 68         //反射方法
 69         Constructor c = clazz.getConstructor(String.class,int.class);
 70         //new
 71         c.newInstance("李四",25);
 72     }
 73     
 74     @Test
 75     public void test5() throws Exception{
 76         //加載類
 77         Class clazz = Class.forName("cn.itcast.reflect.Person");
 78         //反射方法
 79         Constructor c = clazz.getConstructor(List.class);
 80         //new
 81         List list = new ArrayList();
 82         list.add("zhangsan");
 83         list.add("lisi");
 84         list.add("wangwu");
 85         list.add("zhaoliu");
 86         c.newInstance(list);
 87     }
 88     
 89     /*
 90      * 2.普通方法反射
 91      */
 92     @Test
 93     public void test6() throws Exception{
 94         Person p = new Person();
 95         //加載類
 96         Class clazz = Class.forName("cn.itcast.reflect.Person");
 97         
 98         /*
 99          * 反射方法【clazz.getMethod("methodTest", null) 第一個參數爲:方法名;第二個參數爲:方法入參的類型】
100          * 這裏方法入參爲空,因此用null表示參數類型
101          */
102         Method method = clazz.getMethod("methodTest", null);
103         //method.invoke(p, null) 第一個參數要傳一個對象,第二個爲所反射的方法入參
104         method.invoke(p, null);
105     }
106     
107     @Test
108     public void test7() throws Exception{
109         Person p = new Person();
110         //加載類
111         Class clazz = Class.forName("cn.itcast.reflect.Person");
112         //反射
113         Method method = clazz.getMethod("methodTest", String.class);
114         //
115         method.invoke(p, "張三");
116     }
117     
118     @Test
119     public void test8() throws Exception{
120         Person p = new Person();
121         //加載類
122         Class clazz = Class.forName("cn.itcast.reflect.Person");
123         //私有的方法要用getDeclaredMethod來反射獲取
124         Method method = clazz.getDeclaredMethod("methodTest", int.class);
125         //反射出來的方法此時仍是private的,要強制打開訪問權限
126         method.setAccessible(true);
127         //
128         method.invoke(p, 25);
129     }
130     
131     @Test
132     public void test9() throws Exception{
133         //加載類
134         Class clazz = Class.forName("cn.itcast.reflect.Person");
135         //反射
136         Method method = clazz.getMethod("methodTest", String.class, int.class);
137         /*
138          * 靜態的能夠不傳對象,爲:null便可
139          * (第一個參數爲傳對象的位置,後邊的參數都是把反射方法的入參,invoke的「第二個參數」即爲可變參數)
140          */
141         method.invoke(null, "李四", 25);
142     }
143     
144     @Test
145     public void test10() throws Exception{
146         //加載類
147         Class clazz = Class.forName("cn.itcast.reflect.Person");
148         Method method = clazz.getMethod("main", String[].class);
149         //main方法也是個靜態方法
150         /*
151          * 關於下邊註釋的部分,是不能夠用的,由於main方法中的參數爲String[] args,是一個數組,在這裏視爲一個參數
152          * 在jdk1.4以前,沒有「可變參數」,到了1.5之後纔有的可變參數
153          * 那麼,jdk1.4以前的method.invoke(String mehtodName, Object obj[])中
154          * 第二個參數用一個數組Object obj[]來傳參的,在invoke中會把這個數組拆解成爲一個個對應的參數
155          * 而jdk1.5是兼容jdk1.4的,因此,在jdk1.5中用數組來傳參也能夠,固然,它會把這個數組給拆解成幾個參數
156          * 所以,在調用main方法的時候,要在外圍再加一個數組,具體以下【數組參數1/2】
157          * 
158          * 注:反射參數爲數組的方法都要注意
159          */
160         //method.invoke(null, new String[]{"123","234"});
161         //【數組參數1】
162         method.invoke(null, new Object[]{new String[]{"1234","5678","9012"}});
163         //【數組參數2】也能夠這樣(前邊加一個Object能夠欺騙一下程序,騙它爲不是數組,其實傳進去的確實爲數組)
164         method.invoke(null, (Object)new String[]{"1234","5678","9012"});
165     }
166     
167     /*
168      * 3.字段反射
169      */
170     
171     @Test
172     public void test11() throws Exception{
173         Person p = new Person();
174         //加載類
175         Class clazz = Class.forName("cn.itcast.reflect.Person");
176         //參數爲字段名稱
177         Field field = clazz.getField("name");
178         //獲取字段值,傳一個對象進去
179         Object obj = field.get(p);
180         //獲取字段的類型
181         Class type = field.getType();
182         //若是字段類型爲String,則打印數值
183         if(type.equals(String.class)){
184             String value = (String) obj;
185             System.out.println(value);
186         }
187         //設置字段值,第一個參數傳一個對象,第二個參數爲修改的內容
188         field.set(p, "李四");
189         //打印一下,看看能不能經過反射來改變字段的值(結果:能夠)
190         System.out.println(p.name);
191     }
192     
193     @Test
194     public void test12() throws Exception{
195         Person p = new Person();
196         //加載類
197         Class clazz = Class.forName("cn.itcast.reflect.Person");
198         //
199         Field field = clazz.getDeclaredField("age");
200         //私有字段,修改訪問權限
201         field.setAccessible(true);
202         System.out.println(field.get(p));
203     }
204     
205     @Test
206     public void test13() throws Exception{
207         Person p = new Person();
208         //加載類
209         Class clazz = Class.forName("cn.itcast.reflect.Person");
210         Field field = clazz.getDeclaredField("password");
211         field.setAccessible(true);
212         /*
213          * 這裏,password字段爲私有且靜態的字段,
214          * 但靜態字段不一樣於靜態方法和靜態構造方法,field.get(p)中必須傳對象
215          */
216         System.out.println(field.get(p));
217     }
218 }
相關文章
相關標籤/搜索