以前一直只知道有reflect這么一個類是用來反射的,聽人家說java中的反射很難,晚上聽罷張老師講的反射這一節的內容,惶然大悟,原來反射就是把Java類中的各種成分映射成相應的java類。
反射的基礎是要掌握Class這個類的,具體Class的類是干什么的,下面是api文檔中的解釋
可以看出Class類就是一個類或者接口對象的一個實例在內存中的字節碼,而如何得到一個類的字節碼呢?其方法有三:
1 Class<? extends String> cls1 = str1.getClass();
2 Class<String> cls2 = String.class;
3 Class<?> cls3 = Class.forName("java.lang.String");
而Class的isPrimitive()方法就是用來判斷一個類的字節碼是不是9個預定義的class
接下來是Constructor類,Constructor類代表某個類中的一個構造方法。
得到某個類所有的構造方法: 例子:
Constructor [] constructors= Class.forName("java.lang.String").getConstructors();
得到某一個構造方法: 例子:Constructor constructor = Class.forName(“java.lang.String”).getConstructor(StringBuffer.class);//獲得方法時要用到類型
創建實例對象://通常方式:
String str = new String(new StringBuffer("abc"));
//反射方式:
String str = (String)constructor.newInstance(new StringBuffer("abc"));//調用獲得的方法時要用到上面相同類型的實例對象
Class.newInstance()方法: 例子:String obj = (String)Class.forName("java.lang.String").newInstance();
該方法內部先得到默認的構造方法,然后用該構造方法創建實例對象。
該方法內部的具體代碼是怎樣寫的呢?用到了緩存機制來保存默認構造方法的實例對象。
下面是一個Field反射的綜合實例
將任意一個對象中的所有String類型的成員變量所對應的字符串內容中的"b"改成"a"。
首先定義一個ReflectPoint的類
1 package com.anduo.day1;
2
3 public class ReflectPoint {
4 private int x;
5 public int y;
6 public String a = "ball";
7 public String b = "basketball";
8 public String c = "hello";
9
10 public ReflectPoint(int x, int y) {
11 super();
12 this.x = x;
13 this.y = y;
14 }
15
16 @Override
17 public String toString() {
18 return "a=" + a + ";b=" + b + ";c=" + c;
19 }
20 }
21
下面的步驟是:先從對象中得到所有為String類型的字段,2:得到Sting字段的值;3:用String類的replace方法代換a字符為b字符;4:把對象的String字段設置為修改完的新String。
齊活兒
1 package com.anduo.day1;
2
3 import java.lang.reflect.Constructor;
4 import java.lang.reflect.Field;
5
6 public class ReflectTest {
7
8
9 public static void main(String[] args) throws Exception {
10
11
12 /**
13 * 成員變量的反射 Field
14 */
15 System.out.println("**成員變量的反射 Field**");
16 ReflectPoint pt1 = new ReflectPoint(1, -1);
17 Field fieldY = pt1.getClass().getField("y");
18 // fieldY 不是對象身上的變量,而是類上,要用它來去對象上字段的值
19 System.out.println("p1 中 y = " + fieldY.get(pt1));
20 Field fieldX = pt1.getClass().getDeclaredField("x");// 獲取私有屬性字段
21 fieldX.setAccessible(true);// 暴力反射
22 System.out.println("p1 中 x = " + fieldX.get(pt1));
23
24 /**
25 * 將任意一個對象中的所有String類型的成員變量所對應的字符串內容中的"b"改成"a"
26 */
27 changeStringValue(pt1);
28 System.out.println(pt1);
29 }
30
31 /**
32 * 將任意一個對象中的所有String類型的成員變量所對應的字符串內容中的"b"改成"a"
33 * @param obj
34 * @throws IllegalArgumentException
35 * @throws IllegalAccessException
36 */
37 private static void changeStringValue(Object obj) throws IllegalArgumentException, IllegalAccessException {
38 Field[] fields = obj.getClass().getFields();
39 for (Field field : fields) {
40 // if(field.getType().equals(String.class))
41 if (field.getType() == String.class) {
42 String oldValue = (String) field.get(obj);
43 String newValue = oldValue.replace('a', 'b');
44 field.set(obj, newValue);
45 }
46 }
47 }
48
49 }
50
結果如下**成員變量的反射 Field**
p1 中 y = -1
p1 中 x = 1
a=bbll;b=bbsketbbll;c=hello
綜上可以看出,其實反射也沒多難,人家那些寫框架的也不就是用了些反射嗎?把配置文件中的東西讀出來,然后再調用下面的類去做應該做的事情,當然這個過程就用到了反射了。