java基礎學習-反射

反射

JAVA反射機制是在運行狀態中,對於任意一個類,都能夠知道這個類的所有屬性和方法;對於任意一個對象,都能夠調用它的任意一個方法;這種動態獲取的信息以及動態調用對象的方法的功能稱爲java語言的反射機制。

1)關於機制
   Reflection 是Java被視爲動態關鍵性質。這個機制允許程序在APIs取得任何一個已知名稱的cmodifiers(諸如public, stati例如Object)、實現之interfa,也包括fields和methods的所變fields內容或調用methods
2)Java 反射機制主要提供了以下功能:
• 在運行時判斷任意一個對象所屬的類。
• 在運行時構造任意一個類的對象。
• 在運行時判斷任意一個類所具有的成員變量和方法。
• 在運行時調用任意一個對象的方法

Java反射機制實現

1)實現Java反射機制
  主要由以下類來實現Java反射機制,這些類都位於java.lang.reflect包中
– Class類:代表一個類。
– Field 類:代表類的成員變量(成員變量也稱爲類的屬性)。
– Method類:代表類的方法。
– Constructor 類:代表類的構造方法。
– Array類:提供了動態創建數組,以及訪問數組的元素的靜態方法
2)獲取class的三種方式
a) 使用Class類的靜態方法forName:Class.forName(“java.lang.String”);
Class<?> classType = Class.forName(“java.lang.Object”);
Method[] methods = classType.getDeclaredMethods();
b) 使用類的.class 語法:String.class;
 Class<?> classType = InvokeTester.class;
Object invokeTester = classType.newInstance();
Method addMethod = classType.getMethod("add", new Class[] { int.class,
int.class });
Object result = addMethod.invoke(invokeTester, new Object[]{1, 2});
c) 使用對象的getClass()方法:
Fruit e = new Fruit();
classType = (Class<Fruit>) e.getClass();
3)若想通過類的不帶參數的構造方法來生成對象,我們有兩種方式
a) 先獲得Class對象,然後通過該Class對象的newInstance()方法直接生成即可
Class<?> classType = String.class;  
Object obj = classType.newInstance();
b) 先獲得Class對象,然後通過該對象獲得對應的Constructor對象,再通過該Constructor對象的newInstance()方法生成:
Class<?> classType = Customer.class;  
Constructor cons = classType.getConstructor(new Class[]{});   
Object obj = cons.newInstance(new Object[]{});
c)若想通過類的帶參數的構造方法生成對象,只能使用下面這一種方式: 
Class<?> classType = Customer.class;  
Constructor cons = classType.getConstructor(new Class[]{String.class, int.class});   
Object obj = cons.newInstance(new Object[]{“hello”, 3});
4)對象數組
Class<?> classType = Class.forName("java.lang.String");
Object array = Array.newInstance(classType, 10);
Array.set(array, 5, "hello");
String str = (String)Array.get(array, 5);//hello
5)多維數組
 int[] dims = new int[] { 5, 10, 15 };
Object array = Array.newInstance(Integer.TYPE, dims);
Object arrayObj = Array.get(array, 3);
arrayObj = Array.get(arrayObj, 5);
Array.setInt(arrayObj, 10, 37);
int[][][] arrayCast = (int[][][]) array;
6)訪問私有
 Private p = new Private();
Class<?> classType = p.getClass();
Field field = classType.getDeclaredField("name");//獲取屬性
field.setAccessible(true);//壓制Java對訪問修飾符的檢查
field.set(p, "lisi");
Private p = new Private();
Class<?> classType = p.getClass();
//獲取屬性
Method method=classType.getDeclaredMethod("hello",new Class[] { String.class });
method.setAccessible(true);//壓制Java的訪問控制檢查
String str = (String)method.invoke(p, new Object[]{"zhangsan"});
綜合實例
public class TestReflection {

	public static void main(String[] args) throws Exception {
		Class<?> classType = null;
		//獲取類方式一
		classType = Class.forName("com.Fruit");
		//獲取類方式二
		classType = Fruit.class;
		//獲取類方式三
		Fruit e = new Fruit();
		classType = (Class<Fruit>) e.getClass();
		//實例方式一
		Object invokeTester = classType.newInstance();
		//實例方式二 利用構造
		Constructor cons = classType.getConstructor(new Class[]{});   
		invokeTester = cons.newInstance(new Object[]{});
		//方式三 利用帶參構造
		cons = classType.getConstructor(new Class[]{String.class, String.class});
		invokeTester = cons.newInstance(new Object[]{"apple", "red"});
		
		Method addMethod = classType.getMethod("add", new Class[] { int.class,
				int.class });
		Object result = addMethod.invoke(invokeTester, new Object[] { 1, 2 });
		System.out.println(result.toString());//3
		
		//對象數組
		classType = Class.forName("java.lang.String");
		Object array = Array.newInstance(classType, 10);
		Array.set(array, 5, "hello");
		String str = (String)Array.get(array, 5);
		System.out.println(str);//hello
		//多維數組
		int[] dims = new int[] { 5, 10, 15 };
		Object arrayOut = Array.newInstance(Integer.TYPE, dims);
		Object arrayObj = Array.get(arrayOut, 3);
		arrayObj = Array.get(arrayObj, 5);
		Array.setInt(arrayObj, 10, 37);
		int[][][] arrayCast = (int[][][]) arrayOut;
		//訪問私有方法
		classType = Fruit.class;
		Fruit fruit = new Fruit();
		Field field = classType.getDeclaredField("price");
		field.setAccessible(true);//壓制Java對訪問修飾符的檢查
		field.set(fruit, 5);
		System.out.println(fruit.getPrice());//5
		
		Method method=classType.getDeclaredMethod("sell",new Class[] { String.class });
		method.setAccessible(true);//壓制Java的訪問控制檢查
		String methodstr = (String)method.invoke(fruit, new Object[]{"suning"});//sell
	}
}


反射與框架

沒有反射,很多框架就不存在了。(No Reflection,No most frameworks)。
比如讀取配置文件的字符串生成實體(如果是配置則結合註解讀取)
   JUnit4的執行的一般流程: 
a)  首先獲得待測試類所對應的Class對象。 
b)  然後通過該Class對象獲得當前類中所有public方法所對應的Method數組。 
c)  遍歷該Method數組,取得每一個Method對象 
d)  調用每個Method對象的isAnnotationPresent(Test.class)方法,判斷該方法是否被Test註解所修飾。 
e)  如果該方法返回true,那麼調用method.invoke()方法去執行該方法,否則不執行。

反射機制和註解的綜合使用

測試目標類:
public class Goal {
	@MyAnnotation(hello = "aaa", world = "bbb")
	@Deprecated
	@SuppressWarnings("unchecked")
	public void output() {
		System.out.println("output something!");
	}
}
註解類:
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;

@Retention(RetentionPolicy.RUNTIME)
public @interface MyAnnotation{
		String hello() default "hello u";
		String world();
}

測試:
public class Test {

	public static void main(String[] args) throws Exception {
		//反射類
		Class<?> classType = Goal.class;
		Object myTest = classType.newInstance();
		Method method = classType.getDeclaredMethod("output", new Class[]{});
		//註解處理
		if(method.isAnnotationPresent(MyAnnotation.class))		{
			method.invoke(myTest, new Object[]{});
			MyAnnotation myAnnotation = method.getAnnotation(MyAnnotation.class);
			String hello = myAnnotation.hello();
			String world = myAnnotation.world();
			System.out.println(hello + ", " + world);
		}
		Annotation[] annotations = method.getAnnotations();
		for(Annotation annotation : annotations){
			System.out.println(annotation.annotationType().getName());
		}
	}
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章