一、反射
“程式運作時,允許改變程式結構或變量類型,這種語言稱為動态語言”,JAVA有着一個非常突出的動态相關機制:Reflection。
JAVA反射機制是在運作狀态中,對于任意一個類,都能夠知道這個類的所有屬性和方法;對于任意一個對象,都能夠調用它的任意一個方法和屬性;這種動态擷取的資訊以及動态調用對象的方法的功能稱為java語言的反射機制。
Java反射機制,可以實作以下功能:
①在運作時判斷任意一個對象所屬的類;
②在運作時構造任意一個類的對象;
③在運作時判斷任意一個類所具有的成員變量和方法;
④在運作時調用任意一個對象的方法;
⑤生成動态代理。
1.擷取源頭
擷取源頭 Class(重點)
所有類的對象其實都是Class的執行個體。
序列化: 實作serializable接口,
反序列化: 實作cloneable接口,重寫 clone() 方法,修改權限為public
New 反射
//
import java.lang.reflect.Modifier;
public class Demo02 extends Object{
public static void main(String[] args) throws ClassNotFoundException {
//1.類名.class
Class cls1=String.class;
System.out.println(cls1.toString());
//2.對象.getClass()
Class cls2="哈哈".getClass();
System.out.println(cls1==cls2); //true
//3.Class.forName("包名+類名")
Class cls3=Class.forName("java.lang.Object");
System.out.println(cls3);
//根據反射的方式擷取到這個類型的父類的Class對象
Class cls4=cls1.getSuperclass();
System.out.println(cls3==cls4);
//擷取基本資料類型的Class對象
//根據包裝類型.TYPE屬性擷取對應基本資料類型的Class對象
Class cls5=int.class;
Class cls6=Integer.class;
Class cls7=Integer.TYPE;
System.out.println(cls5==cls6);
System.out.println(cls5==cls7);
//getName()
System.out.println(cls1.getName());
//getModifiers()
System.out.println(cls1.getModifiers()); //17
System.out.println(Modifier.toString(cls1.getModifiers())); //public final
}
}
(1)三種
擷取類的class對象,也有三種方式:
①Class.forName(”包名.類名”) //一般盡量采用該形式
②類名.class
③對象.getClass()
2.執行個體化對象(重點)
之前我們了解過的建立對象的方式,有new 、克隆、反序列化,再加一種,根據Class對象,使用newInstance() 或者構造器執行個體化對象。
(1)通過反射擷取構造器,建立對象
通過反射擷取方法,調用方法
Method getDeclaredMethod(String name, Class<?>... parameterTypes) 傳回一個 Method 對象,該對象反映此 Class 對象所表示的類或接口的指定已聲明方法。
Method[] getDeclaredMethods() 傳回 Method 對象的一個數組,這些對象反映此 Class 對象表示的類或接口聲明的所有方法,包括公共、保護、預設(包)通路和私有方法,但不包括繼承的方法。
Method getMethod(String name, Class<?>... parameterTypes) 傳回一個 Method 對象,它反映此 Class 對象所表示的類或接口的指定公共成員方法。
Method[] getMethods() 傳回一個包含某些 Method 對象的數組,這些對象反映此 Class 對象所表示的類或接口(包括那些由該類或接口聲明的以及從超類和超接口繼承的那些的類或接口)的公共 member 方法。
通過反射擷取構造器,建立對象
執行方法:
Object invoke(Object obj, Object... args)
參數1: 調用方法的對象
參數2: 調用方法的實參
傳回值: 調用方法的傳回值
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Arrays;
public class Demo03 {
public static void main(String[] args) throws Exception {
//testConstructor(Person.class);
//testField(Person.class);
testMethod(Person.class);
}
public static void testMethod(Class<Person> cls) throws Exception{
Method[] arr=cls.getMethods();
for(Method me:arr){
System.out.println(me);
}
Person p=cls.newInstance();
Field field=cls.getDeclaredField("name");
field.setAccessible(true);
field.set(p, "lushuangshuang");;
//System.out.println(arr[8].invoke(p));
System.out.println(arr[8].invoke(null)); //null沒有對象
}
//接下
//接下
}
(2)通過反射擷取方法,調用方法
通過反射擷取屬性,擷取值|設定值
Field getField(String name) 傳回一個 Field 對象,它反映此 Class 對象所表示的類或接口的指定公共成員字段。
Field[] getFields()
Field getDeclaredField(String name) 傳回一個 Field 對象,該對象反映此 Class 對象所表示的類或接口的指定已聲明字段。
Field[] getDeclaredFields()
擷取屬性的值: Object get(Object obj)
設定屬性的值: void set(Object obj, Object value)
//接上
public static void main(String[] args) throws Exception {
//testConstructor(Person.class);
//testField(Person.class);
testMethod(Person.class);
}
public static void testField(Class<Person> cls) throws Exception{
Field name=cls.getDeclaredField("name");
//成員要跟随對象使用
Person p=cls.getConstructor(String.class,int.class,Double.TYPE).newInstance("因為",18,100);
name.setAccessible(true);
System.out.println(name.get(p));
name.set(p, "是以");
System.out.println(name.get(p));
name.setAccessible(false);
}
(3)通過反射擷取屬性,擷取值|設定值
通過反射擷取構造器,建立對象
Constructor<T> getConstructor(Class<?>... parameterTypes) 傳回一個 Constructor 對象,它反映此 Class 對象所表示的類的指定公共構造方法。
Constructor<?>[] getConstructors()
Constructor<T> getDeclaredConstructor(Class<?>... parameterTypes) 傳回一個 Constructor 對象,該對象反映此 Class 對象所表示的類或接口的指定構造方法。
Constructor<?>[] getDeclaredConstructors()
建立對象:
通過指定的構造器建立對象,如果私有,放開權限
通過一個類的Class對象的newInstance方法建立這個類的執行個體,預設調用空構造
//接上
public static void main(String[] args) throws Exception {
//testConstructor(Person.class);
//testField(Person.class);
testMethod(Person.class);
}
public static void testConstructor(Class cls) throws InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException, NoSuchMethodException, SecurityException{
Constructor<Person>[] arr=cls.getConstructors(); //所有公共的
System.out.println(Arrays.toString(arr));
//根據構造器的newInstance(實參...)
Person p=arr[0].newInstance("zhangsan",18,180);
System.out.println(p);
Constructor<Person> con=cls.getDeclaredConstructor(String.class);
//放開構造器的權限
con.setAccessible(true);
Person p2=con.newInstance("lisi");
con.setAccessible(false);
System.out.println(p2);
//預設調用空構造
Person p3=(Person) cls.newInstance();
System.out.println(p3);
}