java反射

1.反射機制是什麼?

講到java反射機制,咱們就須要先講一下動態語言的概念,都知道java是一門強類型語言,而動態語言就是在程序的運行期間對屬性的類型進行改變,和狀態的獲取,如(python,javascript)。因此,java就須要利用反射機制在程序的運行狀態中,將一個類的全部成分(屬性,構造器,方法)反射成相對應的類。同時對於任意一個對象,咱們能夠調用它的任意個方法和屬性,這種動態獲取的信息以及動態調用對象的方法的功能稱爲java語言的反射機制。javascript

2.反射機制能作什麼?

  1. 在運行時判斷任意一個對象所屬的類
  2. 在運行時構造任意一個類的對象,並建立實例;
  3. 在運行時獲取類的全部屬性和方法
  4. 在運行時調用任意一個對象的方法
  5. 生成動態代理

3.反射機制相關的API

  1. 已知一個類的名稱(完整的類路徑)在不使用new關鍵字狀況下實例化一個類
//得到類對象
Class clz = Class.forName("edu.hubu.dto.People");
//得到實例
Object obj = clz.newInstance();
  1. //獲取當前類中的全部註解(好比@Deprecated等相似註解)
/獲取當前類中的全部註解
Annotation[] ans = clz.getAnnotations();
for (Annotation annotation : ans) {
    //System.out.println(annotation);
}
  1. 得到指定類中的構造器
//得到公有的構造器(public)
Constructor[] constructs = clz.getConstructors();
for (Constructor constructor : constructs) {
    //System.out.println(constructor);
}
//得到指定類中全部構造器
constructs = clz.getDeclaredConstructors();
for (Constructor constructor : constructs) {
		//System.out.println(constructor);
}
  1. 獲取指定類中的屬性
//得到指定類中全部公有的屬性(public)
			Field[] fields = clz.getFields();
			for (Field field : fields) {
				//System.out.println(field);
			}
			//得到全部的屬性對象
			fields = clz.getDeclaredFields();
			for (Field field : fields) {
				System.out.println(field);
				//得到屬性名稱
				field.getName();
				//得到屬性類型
				field.getType();
				//得到屬性修飾符
				field.getModifiers();
			}
  1. 獲取指定類中的方法
//獲取全部公有方法(public)
			Method[] methods =clz.getMethods();
			//獲取全部方法
			methods = clz.getDeclaredMethods();
			for (Method method : methods) {
				//獲取方法的返回值類型
				method.getReturnType();
				//獲取方法的參數列表
				Class[] types = method.getParameterTypes();
			}
  1. 調用某個對象的方法
    • 好比,咱們在People類中有一個eat方法
public String eat(int age ,String name,String food){
		return age + "歲的" + name + "在吃:" + food;
	}
- 通常咱們會構建一個People實例而後調用這個方法,下面咱們採用反射的方式調用這個方法
//根據給定的方法名和方法執行須要的參數類型集合得到一個Method對象
			Method method = clz.getMethod("eat", new Class[]{int.class,java.lang.String.class,java.lang.String.class});
			//根據method的invoke方法來執行指定類中的eat方法(obj-》指定類的實例,Object[]是參數的值)
			Object o = method.invoke(obj, new Object[]{18,"jack","龍蝦"});

###4. 利用java反射機制,實現對象的拷貝java

  1. 假設咱們有一個People類
public class People {
	public int pid;
	public String pname;
	private int age;
	private double sal;
	public People(){
		
	}
	public People(int pid, String pname, int age, double sal) {
		super();
		this.pid = pid;
		this.pname = pname;
		this.age = age;
		this.sal = sal;
	}
	public People(int pid, String pname) {
		super();
		this.pid = pid;
		this.pname = pname;
	}
	public int getPid() {
		return pid;
	}
	public void setPid(int pid) {
		this.pid = pid;
	}
	public String getPname() {
		return pname;
	}
	public void setPname(String pname) {
		this.pname = pname;
	}
	public int getAge() {
		return age;
	}
	public void setAge(int age) {
		this.age = age;
	}
	public double getSal() {
		return sal;
	}
	public void setSal(double sal) {
		this.sal = sal;
	}
	public String eat(int age ,String name,String food){
		return age + "歲的" + name + "在吃:" + food;
	}
}
  1. 而後咱們定義一個目標對象p,定義一個copy方法,咱們但願副本對象的方法,屬性都與原對象一致。
//目標對象
People p = new People(1,"張三",18,5000);
Object newObj = new ObjectClone().copy(p);
//副本對象
People p2 = (People)newObj;
  1. 在copy()方法中,咱們理應這樣考慮
    • 已知目標類,咱們能夠得到這個類的完整類路徑
target.getClass().getName()
- 得到類路徑以後,咱們即可以獲取類對象,以及得到實例
Class clz = Class.forName(target.getClass().getName());
newObj = clz.newInstance();
- 而後,咱們應該得到類的全部屬性,而後根據屬性獲取setter/getter方法
//得到類屬性
			Field[] fields = clz.getDeclaredFields();
			/**
			 * 根據對象屬性獲取setter/getter方法
			 */
			for (Field f : fields) {
				//獲取屬性名
				String fieldName = f.getName();
				//獲取getter方法的方法名
				String getMethodName = "get" + fieldName.substring(0,1).toUpperCase() + fieldName.substring(1);
				//獲取getter方法對象
				Method method_get = clz.getMethod(getMethodName,new Class[]{});
				
				//獲取setter方法的方法名
				String setMethodName = "set" + fieldName.substring(0,1).toUpperCase() + fieldName.substring(1);
				//獲取setter方法對象
				Method method_set = clz.getMethod(setMethodName,new Class[]{f.getType()});
				
				//執行目標類的get方法獲取返回值
				Object returnValue = method_get.invoke(target, new Object[]{});
				//執行setter方法爲新對象賦值
				method_set.invoke(newObj, new Object[]{returnValue});
  1. 完整源碼以下
public class ObjectClone {
	public Object copy(Object target){
		Object newObj = null;
		try {
			Class clz = Class.forName(target.getClass().getName());
			newObj = clz.newInstance();
			//得到類屬性
			Field[] fields = clz.getDeclaredFields();
			/**
			 * 根據對象屬性獲取setter/getter方法
			 */
			for (Field f : fields) {
				//獲取屬性名
				String fieldName = f.getName();
				//獲取getter方法的方法名
				String getMethodName = "get" + fieldName.substring(0,1).toUpperCase() + fieldName.substring(1);
				//獲取getter方法對象
				Method method_get = clz.getMethod(getMethodName,new Class[]{});
				
				//獲取setter方法的方法名
				String setMethodName = "set" + fieldName.substring(0,1).toUpperCase() + fieldName.substring(1);
				//獲取setter方法對象
				Method method_set = clz.getMethod(setMethodName,new Class[]{f.getType()});
				
				//執行目標類的get方法獲取返回值
				Object returnValue = method_get.invoke(target, new Object[]{});
				//執行setter方法爲新對象賦值
				method_set.invoke(newObj, new Object[]{returnValue});
			}	
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
		} catch (InstantiationException e) {
			e.printStackTrace();
		} catch (IllegalAccessException e) {
			e.printStackTrace();
		} catch (SecurityException e) {
			e.printStackTrace();
		} catch (NoSuchMethodException e) {
			e.printStackTrace();
		} catch (IllegalArgumentException e) {
			e.printStackTrace();
		} catch (InvocationTargetException e) {
			e.printStackTrace();
		}
		return newObj;
	}
	
	public static void main(String[] args) {
		//目標對象
		People p = new People(1,"張三",18,5000);
		Object newObj = new ObjectClone().copy(p);
		//副本對象
		People p2 = (People)newObj;
		System.out.println(p2.getPid()+"\t"+p2.getPname());
	}
}
相關文章
相關標籤/搜索