反射概念:
Java反射是Java被視爲動態(或準動態)語言的一個關鍵性質。這個機制允許程序在運行時透過Reflection APIs取得任何一個已知名稱的class的內部信息,包括其modifiers(諸如public, static 等)、superclass(例如Object)、實現之interfaces(例如Cloneable),也包括fields和methods的所有信息,並可於運行時改變fields內容或喚起methods。
Java反射機制容許程序在運行時加載、探知、使用編譯期間完全未知的classes。
換言之,Java可以加載一個運行時才得知名稱的class,獲得其完整結構。
反射是Java中一種強大的工具,能夠使我們很方便的創建靈活的代碼,這些代碼可以再運行時裝配,無需在組件之間進行源代碼鏈接。但是反射使用不當會成本很高!
JAVA反射機制提供了什麼功能
提供瞭如下功能:
- 在運行時判斷任意一個對象所屬的類
- 在運行時構造任意一個類的對象
- 在運行時判段任意一個類所具有的成員變量和方法
- 在運行時調用任一個對象的方法
- 在運行時創建新類對象
- 在使用Java的反射功能時,基本首先都要獲取類的Class對象,再通過Class對象獲取其他的對象。
反射機制的作用:
- 反編譯:.class–>.java
- 通過反射機制訪問java對象的屬性,方法,構造方法等;
Java中JDK提供的Reflection API
Java反射相關的API在包java.lang.reflect中。
Member接口 該接口可以獲取有關類成員(域或者方法)後者構造函數的信息。
AccessibleObject類 該類是域(field)對象、方法(method)對象、構造函數(constructor)對象的基礎類。它提供了將反射的對象標記爲在使用時取消默認
Java 語言訪問控制檢查的能力。 Array類 該類提供動態地生成和訪問JAVA數組的方法。
Constructor類 提供一個類的構造函數的信息以及訪問類的構造函數的接口。 Field類 提供一個類的域的信息以及訪問類的域的接口。
Method類 提供一個類的方法的信息以及訪問類的方法的接口。
Modifier類 提供了 static方法和常量,對類和成員訪問修飾符進行解碼。
Proxy類 提供動態地生成代理類和類實例的靜態方法。
動態創建代理類
代理模式:代理模式的作用=爲其他對象提供一種代理以控制對這個對象的訪問。
代理模式的角色:
- 抽象角色:聲明真實對象和代理對象的共同接口
- 代理角色:代理角色內部包含有真實對象的引用,從而可以操作真實對象。
- 真實角色:代理角色所代表的真實對象,是我們最終要引用的對象。
動態代理:
- java.lang.reflect.Proxy
Proxy 提供用於創建動態代理類和實例的靜態方法,它還是由這些方法創建的所有動態代理類的超類 - InvocationHandler
是代理實例的調用處理程序 實現的接口,每個代理實例都具有一個關聯的調用處理程序。對代理實例調用方法時,將對方法調用進行編碼並將其指派到它的調用處理程序的 invoke 方法。
動態Proxy是這樣的一種類:
它是在運行生成的類,在生成時你必須提供一組Interface給它,然後該class就宣稱它實現了這些interface。你可以把該class的實例當作這些interface中的任何一個來用。當然,這個Dynamic Proxy其實就是一個Proxy,它不會替你作實質性的工作,在生成它的實例時你必須提供一個handler,由它接管實際的工作。
在使用動態代理類時,我們必須實現InvocationHandler接口
實例練習:
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.List;
public class InvokeTest {
/**
* 利用反射機制實現調用方法
* @param obj
* @param methodName
* @throws NoSuchMethodException
* @throws SecurityException
* @throws IllegalAccessException
* @throws IllegalArgumentException
* @throws InvocationTargetException
*/
public static void test(String methodName) throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {
InvokeTest test=new InvokeTest();
//對象類型
Class<?> cls=test.getClass();
//利用反射機制獲取該類型下的方法
Method method=cls.getMethod(methodName, int.class,String.class);
//執行該方法
method.invoke(test, 10,"20");
// test.method(10,20)
}
/**
* ...代表:一組相同類型的數據(不約束個數)
* 一個方法裏最多只能有一個...類型
* ...類型必須出現在參數列表的最後位置
* @param a
*/
public static void e(int... a) {
for(int i=0;i<a.length;i++) {
System.out.println(a[i]);
}
}
//反射機制
//調用方法
//不知道方法名或屬性名
//通過傳遞參數來實現調用
public static void main(String[] args) {
//...省略參數類型
e(1,2,3,4,5);
//反射機制
try {
test("d");
} catch (NoSuchMethodException e) {
// TODO Auto-generated catch block
//沒有該方法
e.printStackTrace();
} catch (SecurityException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalAccessException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalArgumentException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (InvocationTargetException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public void a() {
System.out.println("aaaaaaaaaa");
}
public void b(int b) {
System.out.println("b="+b);
}
public void c(int a,int b) {
System.out.println("sum="+(a+b));
}
public void d(int a,String b) {
System.out.println(a+b);
}
- 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
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
- 79
- 80
- 81
- 82
- 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
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
- 79
- 80
- 81
- 82
具體功能的實現
反射機制獲取類有三種方法,我們來獲取Employee類型。
//第一種方式:
Classc1 = Class.forName("Employee");
//第二種方式:
//java中每個類型都有class 屬性.
Classc2 = Employee.class;
//第三種方式:
//java語言中任何一個java對象都有getClass 方法
Employeee = new Employee();
Classc3 = e.getClass(); //c3是運行時類 (e的運行時類是Employee)
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
創建對象:獲取類以後我們來創建它的對象,利用newInstance:
Class c =Class.forName("Employee");
//創建此Class 對象所表示的類的一個新實例
Objecto = c.newInstance(); //調用了Employee的無參數構造方法.
- 1
- 2
- 3
- 4
- 1
- 2
- 3
- 4
獲取屬性:分爲所有的屬性和指定的屬性:
a,先看獲取所有的屬性的寫法:
//獲取整個類
Class c = Class.forName("java.lang.Integer");
//獲取所有的屬性?
Field[] fs = c.getDeclaredFields();
//定義可變長的字符串,用來存儲屬性
StringBuffer sb = new StringBuffer();
//通過追加的方法,將每個屬性拼接到此字符串中
//最外邊的public定義
sb.append(Modifier.toString(c.getModifiers()) + " class " + c.getSimpleName() +"{\n");
//裏邊的每一個屬性
for(Field field:fs){
sb.append("\t");//空格
sb.append(Modifier.toString(field.getModifiers())+" ");//獲得屬性的修飾符,例如public,static等等
sb.append(field.getType().getSimpleName() + " ");//屬性的類型的名字
sb.append(field.getName()+";\n");//屬性的名字+回車
}
sb.append("}");
System.out.println(sb);
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
b,獲取特定的屬性,對比着傳統的方法來學習:
public static void main(String[] args) throws Exception{
<span style="white-space:pre"> </span>//以前的方式:
/*
User u = new User();
u.age = 12; //set
System.out.println(u.age); //get
*/
//獲取類
Class c = Class.forName("User");
//獲取id屬性
Field idF = c.getDeclaredField("id");
//實例化這個類賦給o
Object o = c.newInstance();
//打破封裝
idF.setAccessible(true); //使用反射機制可以打破封裝性,導致了java對象的屬性不安全。
//給o對象的id屬性賦值"110"
idF.set(o, "110"); //set
//get
System.out.println(idF.get(o));
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
參考博客:
博客1:
http://blog.csdn.net/liujiahan629629/article/details/18013523
博客2: