一、反射 《java核心技術》 官方套話:能夠分析類能力的程式成為反射。 又通過網上搜索有這句話:反射指程式可以訪問、檢測和修改它本身狀態或行為的一種能力。 反射是用來乾什麼的呢? “明明我自己能直接new一個對象,為什麼它要繞一個圈子,先拿到Class對象,再調用Class對象的方法來創建對象呢, ...
一、反射
《java核心技術》
官方套話:能夠分析類能力的程式成為反射。
又通過網上搜索有這句話:反射指程式可以訪問、檢測和修改它本身狀態或行為的一種能力。
反射是用來乾什麼的呢?
“明明我自己能直接new一個對象,為什麼它要繞一個圈子,先拿到Class對象,再調用Class對象的方法來創建對象呢,這不是多餘嗎?”
說不出來,大體作用就是方便,以前只在JDBC用過,看了這邊文章後發現springMVC也用。。。。。。我學個寂寞
https://www.cnblogs.com/Java3y/p/12320363.html
說說你對 Java 中反射的理解
Java中的反射首先是能夠獲取到Java中要反射類的位元組碼,獲取位元組碼有三種方法,
- Class.forName(className)
- 類名.class。
- obj.getClass()
然後將位元組碼中的方法,變數,構造函數等映射成相應的Method、Filed、Constructor等類,這些類提供了豐富的方法可以被我們所使用。
1、反射機制
反射是一種功能強大且複雜的機制,反射機制可以用來:
- 在運行時分析類的能力
- 在運行時查看對象
- 實現通用的數組操作代碼
- 利用Method對象,這個對象很像C++中的函數指針
這個method對象找了很多資料,還是沒太搞明白
2、Class類
獲取Class類對象的三種方法:
- 常用的有getClass()方法將返回一個Class類型的實例,getName()方法將返回類的名字。
- 可以調用靜態方法forName()獲取類名對應的Class對象。
- 如果T是任意java類型(或者void關鍵字),T.class將代表匹配的類對象。
1 package Reflect; 2 3 public class Person {}
Student和Teacher都是Person類的子類
package Reflect; public class test { public static void main(String[] args) throws ClassNotFoundException { Person student = new Student(); Person teacher = new Teacher(); Object obj=new Object(); System.out.println(student.getClass()); System.out.println(teacher.getClass()); System.out.println(obj.getClass()); // class Reflect.Student // class Reflect.Teacher // class java.lang.Object System.out.println(student.getClass().getName()); System.out.println(teacher.getClass().getName()); System.out.println(obj.getClass().getName()); // Reflect.Student // Reflect.Teacher // java.lang.Object Class c1=Class.forName("Reflect.Person"); System.out.println(c1); // class Reflect.Person Class c2= Person.class; System.out.println(c2); // class Reflect.Person
Class c3=int.class;
System.out.println(c3);
// int,註意,一個Class對象實際上表示的是一個類型,而這個類型未必一定是一種類,比如這裡的int不是類,但int.class是一個Class類型的對象
}
}
獲取類對象可以搭配newInstance動態的創建一個類的實例!(調用的是類的預設無參構造器,如果沒有會拋出異常)
3、檢查類的結構
在java.lang.reflect包中有三個類Field,Method,Constructor分別用於描述類的域,方法,構造器。這三個類都有一個getName的方法,用來返回項目的名稱。
常用的方法有:
Field類:getType() :返回描述域所屬類型的Class對象
getModifiers():返回一個整形數值,用不同的位開關描述public和static這樣的修飾符使用情況
Method類:getReturnType():方法的返回類型
getParameterTypes():參數的類型
Constructors類:getParameterTypes():參數的類型
Class類:getFileds(),getMethods()和getConstructors()返回類提供的public域,方法,構造器,其中包括超類的公有成員
getDeclareFields(),getDeclareMethods(),getDeclareConstructors()將返回類中聲明的全部域,方法和構造器,其中包括私有和受保護,但不包括超類成員
package Reflect;
import sun.management.MethodInfo;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.Scanner;
public class ClassConstruct {
public static void main(String[] args) {
String name;
if (args.length > 0){
name=args[0];
}else {
Scanner in = new Scanner(System.in);
System.out.println("輸入類名(eg:java.util.Date)");
name=in.next();
}
try {
Class c1=Class.forName(name);
Class superc1=c1.getSuperclass();//獲得父類的對象
String modifiers= Modifier.toString(c1.getModifiers());//返回一個整形數值,用不同的位開關描述public和static這樣的修飾符使用狀況
if (modifiers.length()>0){
System.out.print(modifiers+" ");
}
System.out.print("class:"+name);
if (superc1 !=null && superc1 !=Object.class ){
System.out.print(" extends "+superc1.getName());
}
System.out.print("\n{\n");
printConstructors(c1);//列印出c1的構造器
System.out.println();
printMethods(c1);//列印出c1的方法
System.out.println();
printFields(c1);//列印出c1的域
}catch (ClassNotFoundException e){
e.printStackTrace();
}
System.out.println("}");
System.exit(0);
}
/**
* 列印出c1類的全部構造器
* @param c1
*/
private static void printConstructors(Class c1) {
Constructor[] constructors=c1.getDeclaredConstructors();//返回類的全部構造器
for (Constructor c:constructors) {
String name=c.getName();
System.out.print(" ");
String modifiers=Modifier.toString(c.getModifiers());
if (modifiers.length()>0){
System.out.print(modifiers+" ");
}
System.out.print(name+" (");
//列印參數類型
Class[] paramTypes=c.getExceptionTypes();
for (int i=0;i<paramTypes.length;i++){
if (i>0){
System.out.print(paramTypes[i].getName());
}
}
System.out.print(" );");
}
}
/**
* 列印出c1類的全部方法
* @param c1
*/
private static void printMethods(Class c1) {
Method[] methods=c1.getDeclaredMethods();
for (Method m:methods){
Class retType=m.getReturnType();//方法的返回類型
String name=m.getName();//獲得方法名
System.out.print(" ");
//列印public或static,返回類型和方法名
String modifiers=Modifier.toString(m.getModifiers());
if (modifiers.length()>0){
System.out.print(modifiers+" ");
}
System.out.print(retType.getName()+" "+name+" (");
//列印參數類型
Class[] paramType=m.getParameterTypes();
for (int i = 0; i <paramType.length ; i++) {
if (i>0){
System.out.print(",");
}
System.out.print(paramType[i].getName());
}
System.out.println(");");
}
}
/**
* 列印出c1類的全部域
* @param c1
*/
private static void printFields(Class c1) {
Field[] fields=c1.getDeclaredFields();
for (Field f:fields) {
Class type=f.getType();//得到域的類型
String name=f.getName();
System.out.print(" ");
String modifiers=Modifier.toString(f.getModifiers());
if (modifiers.length()>0){
System.out.print(modifiers+" ");
}
System.out.println(type.getName()+ " "+name+" ;");
}
}
}
控制台輸入一個類:eg:java.lang.Double,輸出:
public final class:java.lang.Double extends java.lang.Number { public java.lang.Double ( ); public java.lang.Double ( ); public boolean equals (java.lang.Object); public static java.lang.String toString (double); public java.lang.String toString (); public int hashCode (); public static int hashCode (double); public static double min (double,double); public static double max (double,double); public static native long doubleToRawLongBits (double); public static long doubleToLongBits (double); public static native double longBitsToDouble (long); public volatile int compareTo (java.lang.Object); public int compareTo (java.lang.Double); public byte byteValue (); public short shortValue (); public int intValue (); public long longValue (); public float floatValue (); public double doubleValue (); public static java.lang.Double valueOf (java.lang.String); public static java.lang.Double valueOf (double); public static java.lang.String toHexString (double); public static int compare (double,double); public static boolean isNaN (double); public boolean isNaN (); public static boolean isFinite (double); public static boolean isInfinite (double); public boolean isInfinite (); public static double sum (double,double); public static double parseDouble (java.lang.String); public static final double POSITIVE_INFINITY ; public static final double NEGATIVE_INFINITY ; public static final double NaN ; public static final double MAX_VALUE ; public static final double MIN_NORMAL ; public static final double MIN_VALUE ; public static final int MAX_EXPONENT ; public static final int MIN_EXPONENT ; public static final int SIZE ; public static final int BYTES ; public static final java.lang.Class TYPE ; private final double value ; private static final long serialVersionUID ; } Process finished with exit code 0
在運行時使用反射分析對象
查看對象域的關鍵方法是Field類中的get方法,如果f是Field類型的對象,obj是某個包含f域的類的抽象,f.get(obj)將返回一個對象,其值為obj域的當前值。
public class Person { public String name; public int val; public Person(String name,int val){ this.name=name; this.val=val; } }
public class ReflectTest { public static void main(String[] args) throws NoSuchFieldException, IllegalAccessException { Person person=new Person("Curry",1000); Class c1=person.getClass(); Field f=c1.getDeclaredField("val");//獲取它對象的某個域 Object v=f.get(person);// System.out.println(v);
//1000 } }
這裡Person類中如果域的訪問許可權是private,則將會出錯
Exception in thread "main" java.lang.IllegalAccessException: Class Reflect.ReflectTest can not access a member of class Reflect.Person with modifiers "private" at sun.reflect.Reflection.ensureMemberAccess(Reflection.java:102) at java.lang.reflect.AccessibleObject.slowCheckMemberAccess(AccessibleObject.java:296) at java.lang.reflect.AccessibleObject.checkAccess(AccessibleObject.java:288) at java.lang.reflect.Field.get(Field.java:390) at Reflect.ReflectTest.main(ReflectTest.java:10)
get()方法只能得到可訪問域的值,除非擁有許可權,否則java的安全機制只允許查看任意對象有哪些域,而不允許讀取他們的值。
反射機制的預設行為受限於java的訪問控制,然而如果一個java程式沒有受到安全管理器的控制,就可以覆蓋訪問控制。為了達成目的,需要調用Field,Method或Constructors對象的setAccessible()
public class ReflectTest { public static void main(String[] args) throws NoSuchFieldException, IllegalAccessException { Person person=new Person("Curry",1000); Class c1=person.getClass(); Field f=c1.getDeclaredField("val"); f.setAccessible(true); Object v=f.get(person); System.out.println(v);
//1000 } }
發現現在可以訪問了
f.set(person,1900); 設置新值
4、反射機制的動態代理
摘自於https://www.cnblogs.com/lzq198754/p/5780331.html
public interface Subject { public String say(String name, int age); } class RealSubject implements Subject { public String say(String name, int age) { return name + " " + age; } }
//如果想要完成動態代理,首先需要定義一個InvocationHandler介面的子類,已完成代理的具體操作。 class MyInvocationHandler implements InvocationHandler { private Object obj = null; public Object bind(Object obj) { this.obj = obj; return Proxy.newProxyInstance(obj.getClass().getClassLoader(), obj.getClass().getInterfaces(), this); } public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { Object temp = method.invoke(this.obj, args); return temp; } }
public class ProxyTest { public static void main(String[] args) throws Exception { MyInvocationHandler demo = new MyInvocationHandler(); Subject sub = (Subject) demo.bind(new RealSubject()); String info = sub.say("Rollen", 20); System.out.println(info);
//Rollen 20
} }
二、泛型