Java 反射機制

反射的概念

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>



發佈了109 篇原創文章 · 獲贊 39 · 訪問量 17萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章