天天看點

黑馬程式員-反射的應用

------- android教育訓練、java教育訓練、期待與您交流! ----------

一、Constructor類

Constructor[] cons = String.class.getConstructors();			//得到String類的所有的構造方法
		
Constructor con = String.class.getConstructor(StringBuffer.class);	//得到StringBuffer類的一個的構造方法
String str = (String)con.newInstance(new StringBuffer("abc"));		//執行個體化Constructor對象
           

這裡需要說明一下,

1、想要得到哪個構造方法的Constructor類就在getConstructor()方法裡寫上想得到的構造方法所傳的參數類型的位元組碼;

2、在将Constructor進行執行個體化的時候的newInstance()方法中寫的是這個構造函數所傳參數的對象

3、最後需要将執行個體化對象強制轉換成String類型,因為執行個體化之後傳回類型是Object

String.class.newInstance();
           

最後也可以直接用過String類的位元組碼直接通過newInstance()方法,得到String的無參構造方法,然後通過無參的構造方法建立String的執行個體化對象,這個最後得到的也是Object,是以也要進行強制轉換的哦

二、Field類

先寫一個ReflectField類,記錄兩個變量,一個私有的x和一個共有的y,并建立有參的構造方法

private int x;
public int y;

public ReflectField(int x, int y) {
		super();
		this.x = x;
		this.y = y;
	}
           
ReflectField rf1 = new ReflectField(6,8);
//Field[] fields = rf1.getClass().getFields();//得到所有的變量放入到Field數組
Field fieldY = rf1.getClass().getField("y");
System.out.println(fieldY.get(rf1));
		
Field fieldX = rf1.getClass().getDeclaredField("x");
fieldX.setAccessible(true);		//暴力反射
System.out.println(fieldX.get(rp1));
           

需要注意的

1、得到ReflectField類的位元組碼後getField()方法這裡需要寫的是變量名

2、隻是把y變量指派給了fieldY,如果想得到y的值那麼還要确定是哪個對象的裡的y,是以fieldY的get()方法這裡寫的就是 ReflectField對象

3、由于x是私有的,是以如果想通路到變量x,就要用getDeclaredField()方法,将x變量指派給fieldX;如果想列印x變量,則需要設定一個屬性setAccessible(true)後就可以正常列印了

下邊做一個練習,将一個對象裡所有的String類型的變量所對應的字元串,将b改成Z

public static void ChangeValue(Object obj) {
	Field[] fds = obj.getClass().getFields();
	for(Field fd: fds)
	{
		try {
			if (fd.getType() == String.class) {
				String oldstr = (String) fd.get(obj);
				String newstr = oldstr.replace('b', 'Z');
				fd.set(obj, newstr);

			}
		} catch (Exception e) {
			
			throw new RuntimeException(e); 
		}
	}

}
           

注意:

1、field.getType()擷取field這個變量的類型

2、如果類中的成員變量沒有權限修飾,那麼getFields()就需要變成getDeclaredFields();

三、Medthod類

String str1 = "abc";
Method methodCharAt = String.class.getMethod("charAt", int.class);//把String的charAt()方法賦給methodCharAt變量
System.out.println(methodCharAt.invoke(str1, 1));//調用methodCharAt的invoke()方法,列印結果為b
System.out.println(methodCharAt.invoke(str1, new Object[]{1}));//jdk1.4之前的書寫方式,列印結果也是b
           

注意:

1、這裡getMethod(),這裡第一個是這個方法的名字;後邊是這個方法傳的參數

2、invoke()這裡的str1是對象,後邊的1是要給charAt這個方法傳的參數(即,調用str1對象的chartAt(1)方法)

3、如果invoke()方法的第一個參數是null,那麼這個charAt()方法不需要通過對象就可以調用,由此可以得出這個方法是靜态方法。

四、數組的應用

Class cls = Class.forName("java.lang.String"); 
Object arr = Array.newInstance(cls, 10); //執行個體化一個長度為10的String類型數組
Array.set(arr, 5, "this is a test"); //将數組的第五個位置替換成"this is a test"
String s = (String) Array.get(arr, 5); //得到數組的第五個位置,并強制轉換成String類型
System.out.println(s); 
           
Class cla = obj.getClass();
	if(cla.isArray()){		//判斷cla是不是數組類型
		for(int i=0;i<Array.getLength(obj);i++){
			System.out.println(Array.get(obj, i));
		}
	}else{
		System.out.println(obj);
	}
           

判斷如果是數組類型就挨個列印數組裡的元素,如果不是數組類型就直接列印