1. 程式人生 > 實用技巧 >【Java】反射機制

【Java】反射機制

反射

反射:是底層技術 (開發工具和框架,使程式碼更通用)
java.lang.reflect//反射包

1).類物件Class

是類載入的產物,封裝了一個類的所有資訊(類名,父類,介面,屬性,方法,構造方法…)

類載入: 當JVM第一次使用一個類的時候,需要讀取這個類對應的位元組碼檔案,獲取類的資訊並儲存起來
類物件: 記錄類的資訊的物件. 類載入後,將類的資訊封裝成類物件,儲存在方法區中

	獲得類物件的三種方法:
①	Class c1 = HashMap.class; //獲取類物件

		②	Object o = new HashMap();
			Class c2 = o.getClass();
		
		③	String className = “java.util.HashMap”; 	//寫類的全名,帶包
			Class c3 = Class.forName(className); 		//Class.forName, 載入

	常用方法:
		getName()				 		獲取全類名
		getSimpleName() 					獲取簡單類名,不含包名
		getSuperClass() 					獲取父類的類物件
		getInterfaces() 					獲取所有實現了的介面類物件,返回Class[]
		getField()							獲取一個公開屬性物件, 
		getDeclaredField()	 				獲取一個屬性,包括非公開的
		getFields()						獲取所有的公開屬性物件,包括繼承自父類的屬性
		getDeclaredFields()	 				獲取本類中所有的屬性物件,
		getMethod(“方法名”,引數表.class)		獲取一個公開方法,注意引數表的位子
		getDeclaredMethod(“方法名”,引數表.class)獲取一個本類的方法,包括非公開的
		getMethods() 					獲取所有的公開方法,包括父類的
getDeclaredMethods() 				獲取本類所有的方法
getConstructors() 					返回所有的構造方法的物件資訊
		
	用法:例
		Class c = HashMap.class;
		System.out.println(c.getName());					//帶包名,全名
		System.out.println(c.getSimpleName());				//不帶包名,簡單名
		System.out.println(c.getSuperclass().getName());	//父類的帶包名
		
Class[] cc = c.getInterfaces();						//獲得實現的介面
		for(int i = 0; i < cc.length; i++) {				//遍歷以實現的介面並列印名字
			System.out.println(cc[i].getName());}

2).Field

Field:封裝一個類物件的所有屬性資訊
	常用方法:
		getFields();返回類中所有的公開屬性,包括父類中的屬性,返回Field陣列
		getDeclaredFields();返回本類中所有屬性,包括非公開屬性,返回Field陣列
	用法:
		class Student { public String name; public int age;}
		main();
			Class c = Student.class;
			Field[] f = c.getFields();
			for(int i = 0; i < f.length; i++) {
				System.out.println(f[i]);
			}

3).Method

Method:封裝一個類物件的所有方法資訊
	常用方法:
		getMethod(“方法名”, 此方法的引數表(例如Object.class));返回類中的一個方法,
getDeclaredMethod(“方法名”, 此方法的引數表(例如Object.class)); 獲取的一個包括非公開的方法
		getMethods();返回類中所有的公開方法,包括父類中的方法,返回Method陣列
		getDeclaredMethods();返回本類中所有方法,包括非公開方法,返回Method陣列

	用法:
	①  Class c = HashMap.class;
		Method m1 = c.getMethod(“put”);//返回無參put方法
		m1 = c.getMethod(“put”, Object.class, Object.class);//返回有兩個Object型別引數的put方法
System.out.println(m1.getReturnType().getName());//列印該方法的返回值型別名稱

	②  Method[] m2 = c.getMethods(); //返回類物件c內的所有公開方法,包括父類的方法
		for(int i = 0; i < m2.length; i++) {
			System.out.println(m2[i].getName());
		}

③  Method[] m3 = c.getMethods(); //返回類物件c內的所有非公開方法
		for(int i = 0; i < m3.length; i++) {
			System.out.println(m3[i].getName());
		}

3).Constructor

Constructor:封裝一個類物件所有構造方法資訊
	常用方法:
	getConstructos();返回類中所有的構造方法,包括父類中的方法,返回Constructor陣列
	
	用法:
		Class c = Student.class;
		Constructor[] ct = c.getConstructors(); //獲取所有構造方法
		System.out.println(ct[0].getName());

4).利用反射處理類的物件(例項化物件、呼叫方法)

	動態對類做操作:
		①對Class物件呼叫newInstance(),可以建立該類的物件呼叫無參構造方法
			Class c = Class.forName(“com.baizhi.Student”); //注意拋異常
			c.newInstance();
		②對Method物件呼叫invoke(Object o),對o呼叫方法
			Method m = 物件.getMethod(“方法名”,引數型別.class);
			m.invoke(o);
		③可以呼叫私有方法,但必須先將方法的可訪問性屬性改為true(setAccessible(true))
			Method m = 物件.getDeclaredMethod(“方法名”,引數型別.class);//私有方法
			m.setAccessible(true); //修改可訪問性
			m.invoke(o);
		④訪問並設定物件的屬性

	用法:
		class Student { 
			public void study() { System.out.pritln(“在學習”);}
	public String study(String course) { return “學習課程:” + course; }
}
main():
	//Student o = new Student();
	Class c = Class.forName(“包.Student”);//載入類Student
	Object o = c.newInstance();//建立類的物件

	//o.study();呼叫無參方法
	Method m1 = c.getDeclaredMethod(“study”); //獲取無參的study方法
	m1.invoke(o); //呼叫方法
	
	//o.study();呼叫有參方法
	Method m2 = c.getDeclaredMethod(“study”, String.class); //獲取方法
	Object result = m2.invoke(o, “CoreJava”); //呼叫有參構造,並將返回值賦給o
	System.out.println(result);