反射的概念
1、反射被看作是動態語言的關鍵,反射機制允許程序在執行期間藉助Reflect的API取得任何類的內部信息以及操作內部屬性和方法。
Class類
1、Class類被定義爲反射的源頭。在Object類中定義了public final Class getClass(){}這個方法來獲取運行時類Class,這個Class可以保存類的運行時信息。
2、有了反射,可以通過反射創建一個對象,並調用其中的結構。一般來說,有三種方法來獲取對象的運行時類Class:
先建立一個User類,這個User 定義一些成員變量,成員方法等
<span style="font-size:14px;">package com.reflect;
public class User {
private String userName;
private int age;
public User() {}
public User(String userName, int age) {
super();
this.userName = userName;
this.age = age;
}
public String doWork(String work){
return "the User is working with"+work;
}
}</span>
下面就是創建運行時類的三種方法:a、調用運行時類的本身的Class屬性
<span style="font-size:14px;">Class clazz=User.class;</span>
b、通過運行時類對象
<span style="font-size:14px;">User u=new User();
Class clazz=u.getClass();</span>
c、通過Class的靜態方法
<span style="font-size:14px;">Class clazz=Class.forName("com.reflect.User");</span>
當創建了運行時類Class以後,可以通過反射來獲取類的信息,以及調用類的方法。
java.lang.reflect
1、這個包是用來分析類的相關信息,可以通過這個包裏面的Field、Method、Constructor這三個類來實現對類信息的動態捕獲。
2、java.lang.reflect.Field使用方法,類裏的方法主要是用來獲取類的成員變量如下例子:
package com.reflect;
import java.io.ObjectInputStream.GetField;
import java.lang.reflect.Field;
public class reflect_demo {
public static void main(String[] args) {
Class clazz=User.class;
Field [] fields=clazz.getDeclaredFields();//獲取聲明的所有屬性
//Field fields=clazz.getDeclaredField("age");//獲取聲明爲age的屬性
//Field [] fields=clazz.getFields();//獲取爲訪問權限爲public的屬性
//clazz.getField("age");//獲取訪問權限爲public且聲明爲age的屬性
for (Field field : fields) {
String name=field.getName();//獲取屬性名
int modify=field.getModifiers();
}
}
}
3、java.lang.reflect.Method使用方法,主要是用來獲取類的成員方法
package com.reflect;
import java.lang.reflect.Method;
public class reflect_demo {
public static void main(String[] args) throws Exception{
Class clazz=User.class;
Method [] methods=clazz.getMethods();//獲取所有的public方法
// Method method=clazz.getMethod("work");
// Method [] methods=clazz.getDeclaredMethods();//獲取類聲明的所有方法
// Method method=clazz.getDeclaredMethod("work");
for (Method method : methods) {
String name=method.getName();//方法名
String returnType=method.getReturnType().getName();//方法返回類型
Class [] params=method.getParameterTypes();//方法形參列表
int modify=method.getModifiers();//方法權限修飾
Class [] exceptions=method.getExceptionTypes();//拋出異常列表
}
//動態調用一個方法
Method method=clazz.getDeclaredMethod("doWork", String.class);
Object result=method.invoke(clazz.newInstance(), "teacher");
}
}
上面對於Method類的方法只列舉了一些重要常用的,其它方法可以參考JDK API查看4、java.lang.reflect.Constructor使用方法
<span style="font-size:14px;">package com.reflect;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
public class reflect_demo {
public static void main(String[] args) throws Exception{
Class clazz=User.class;
Constructor [] constructors=clazz.getConstructors();//獲取聲明爲public的構造函數
//Constructor [] constructor=clazz.getDeclaredConstructors();//獲取所有的構造函數
}
}</span>
Constructor的其它方法與Method類的方法有些類似此外就不再詳細敘述,有興趣的可以參考JDK API
反射的應用
反射的動態語言的關鍵,java中的一個重要的動態代理就是用反射來實現的,下面就是動態代理的簡單實現過程:
<span style="font-size:14px;">package com.reflect;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
//動態代理的使用,反射是動態語言的關鍵
interface Subject{
public void action();
}
//被代理類
class RealSubject implements Subject{
@Override
public void action() {
System.out.println("我是被代理的對象類,被代理執行");
}
}
//接口
interface ClothFactory {
public void productCloth();
}
//被代理類
class NikeClothFactory implements ClothFactory{
@Override
public void productCloth() {
System.out.println("Nike工廠生產一批衣服");
}
}
class MyInvocationHandler implements InvocationHandler{
Object obj;//實現了接口被代理類的對象的聲明
//給被代理類的對象實例化,返回一個代理類的對象
public Object blind(Object obj){
this.obj=obj;
return Proxy.newProxyInstance(obj.getClass().getClassLoader(), obj.getClass().getInterfaces(), this);
}
//當通過代理類的對象發起對被重寫的方法調用時,都會轉換爲對如下的invoke方法的調用
@Override
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
//method方法的返回值是returnVal
Object returnVal= method.invoke(obj, args);
return returnVal;
}
}
public class TestProxy {
public static void main(String[] args) {
//1、被代理類的對象、
RealSubject real=new RealSubject();
//2、創建一個實現了InvocationHandler接口的類對象
MyInvocationHandler handler=new MyInvocationHandler();
//3、調用blind方法,動態的返回一個同樣實現了real所在類實現的接口的代理類的對象
Object obj=handler.blind(real);
Subject sub=(Subject)obj;//此時sub就是代理類對象
//4、
sub.action();//轉到對InvocationHandler接口的實現類Invoke方法的調用
//
NikeClothFactory nike=new NikeClothFactory();//創建被代理對象
ClothFactory proxyCloth=(ClothFactory) handler.blind(nike);
proxyCloth.productCloth();
}
}</span>