反射是什麼?(概念)
JAVA反射機制是在運行狀態中,對於任意一個類,都能夠知道這個類的所有屬性和方法;對於任意一個對象,都能夠調用它的任意方法和屬性;這種動態獲取信息以及動態調用對象方法的功能稱爲java語言的反射機制。
JAVA反射(放射)機制:“程序運行時,允許改變程序結構或變量類型,這種語言稱爲動態語言”。從這個觀點看,Perl,Python,Ruby是動態語言,C++,Java,C#不是動態語言。但是JAVA有着一個非常突出的動態相關機制:Reflection,用在Java身上指的是我們可以於運行時加載、探知、使用編譯期間完全未知的classes。換句話說,Java程序可以加載一個運行時才得知名稱的class,獲悉其完整構造(但不包括methods定義),並生成其對象實體、或對其fields設值、或喚起其methods。
反射提供的功能
對任何一個對象,都能夠調用這個對象它的任意一個方法和屬性。
對於任何一個類,都能夠知道它的任意方法屬性。
1、在運行時,判斷一個對象所屬類
2、在運行時,構造任意一個類的對象
3、在運行時,判斷一個類所具有的方法和屬性
4、在運行時,調用任意一個對象的方法
5、生成動態代理
正文
一、反射入口
牢牢記住面代碼,只要使用了反射,這段代碼必定是不可少的
Class<?> perClazz = null;
//Class入口
try {
perClazz= Class.forName("reflect.Person");
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
二、獲取類名(三種方式)
//獲取類名(包.類名)
public static void demo01() {
//反射獲取類:Class -> 1.Class.forName(全類名) 2.xx.class 3.getClass()
//Class入口
try {
//方法一
Class<?> perClazz = Class.forName("reflect.Person");
System.out.println(perClazz);
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
//方法二
Class<?> perClazz2 = Person.class;
System.out.println(perClazz2);
//方法三
Person per = new Person();
Class<?> perClazz3 = per.getClass();
System.out.println(perClazz3);
}
三、獲取方法名
這裏值得注意的是,獲取方法可以分爲兩種:
1、獲取所有的公共方法(本類、父類、接口類)
2、獲取本類的所有方法(包括 私有 等等)
//獲取方法
public static void demo02() {
Class<?> perClazz = null;
//Class入口
try {
perClazz= Class.forName("reflect.Person");
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
//獲取 所有公共方法(1、本類以及父類以及接口類所有方法。2、符合訪問修飾符規律)
Method[] methods = perClazz.getMethods();
for(Method method : methods) {
System.out.println(method);
}
System.out.println("=====================");
//獲取 當前類的 所有 方法(只能時當前類, 忽略訪問修飾符)
Method[] declaredMethods = perClazz.getDeclaredMethods();
for(Method de:declaredMethods) {
System.out.println(de);
}
}
四、獲取接口
//獲取所有接口
public static void demo03() {
Class<?> perClazz = null;
//Class入口
try {
perClazz= Class.forName("reflect.Person");
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
Class<?>[] interfaces = perClazz.getInterfaces();
for(Class<?>inter:interfaces) {
System.out.println(inter);
}
}
五、獲取父類I(只有一個,單繼承多實現)
//獲取父類
public static void demo04() {
Class<?> perClazz = null;
//Class入口
try {
perClazz= Class.forName("reflect.Person");
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
Class<?> superclass = perClazz.getSuperclass();
System.out.println(superclass);
}
六、獲取構造方法
//獲取構造方法
public static void demo05() {
Class<?> perClazz = null;
//Class入口
try {
perClazz= Class.forName("reflect.Person");
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
Constructor<?>[] constructors = perClazz.getConstructors();
for(Constructor con:constructors) {
System.out.println(con);
}
}
七、獲取屬性
屬性跟方法一樣,有公共屬性和私有屬性,獲取方法和方法一樣
//獲取屬性
public static void demo06() {
Class<?> perClazz = null;
//Class入口
try {
perClazz= Class.forName("reflect.Person");
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
//獲取所有公共屬性
Field[] fields = perClazz.getFields();
for(Field fie:fields) {
System.out.println(fie);
}
System.out.println("============================");
//獲取當前類所有屬性
Field[] declaredFields = perClazz.getDeclaredFields();
for(Field df:declaredFields) {
System.out.println(df);
}
}
八、總結
1、看了這麼多,可以發現的是,不管獲取什麼,反射入口都是一樣的。
2、不管Java有什麼,反射都能獲取得到。
3、獲取的方法名都差不多(.getxxx)
(1)field:屬性 ------- fields:所有屬性
(2)method: 方法 ------ methods:所有方法
(3)constructor : 構造方法 ---------constructors:所有構造方法
(4)superclass : 父類
(5)interface:接口---------interfaces:所有接口