Java反射筆記

Java反射 之 初體驗

    筆者最近在java編程實踐中接觸到Java的反射機制,於是粗淺地做了一些瞭解,在此記錄一下。

    java反射的主要作用體現在爲JVM動態加載類,獲取類的成員,方法,構造器等提供了一種手段。    

   Java反射框架主要提供以下功能:

  •         1.在運行時判斷任意一個對象所屬的類;
  •         2.在運行時構造任意一個類的對象;
  •         3.在運行時判斷任意一個類所具有的成員變量和方法(通過反射甚至可以調用private方法);
  •         4.在運行時調用任意一個對象的方法
    重點:是運行時而不是編譯時

       反射的主要用途在於開發框架,很多框架(比如Spring)都是配置化的(比如通過XML文件配置JavaBean,Action之類的),爲了保證框架的通用性,它們可能需要根據配置文件加載不同的對象或類,調用不同的方法,這個時候就必須用到反射——運行時動態加載需要加載的對象。

1、獲得Class對象

方法有三種
(1)使用Class類的forName靜態方法:

1
2
3
4
5
public static Class<?> forName(String className)
```
在JDBC開發中常用此方法加載數據庫驅動:
```java
Class.forName(driver);

(2)直接獲取某一個對象的class,比如:

1
2
Class<?> klass = int.class;
Class<?> classInt = Integer.TYPE;

(3)調用某個對象的getClass()方法,比如:

1
2
StringBuilder str = new StringBuilder("123");
Class<?> klass = str.getClass();

2、判斷是否爲某個類的實例

一般地,我們用instanceof關鍵字來判斷是否爲某個類的實例。同時我們也可以藉助反射中Class對象的isInstance()方法來判斷是否爲某個類的實例,它是一個Native方法:

1
public native boolean isInstance(Object obj);

3、創建實例

通過反射來生成對象主要有兩種方式。
(1)使用Class對象的newInstance()方法來創建Class對象對應類的實例。

1
2
Class<?> c = String.class;
Object str = c.newInstance();

(2)先通過Class對象獲取指定的Constructor對象,再調用Constructor對象的newInstance()方法來創建實例。這種方法可以用指定的構造器構造類的實例。

1
2
3
4
5
6
7
//獲取String所對應的Class對象
Class<?> c = String.class;
//獲取String類帶一個String參數的構造器
Constructor constructor = c.getConstructor(String.class);
//根據構造器創建實例
Object obj = constructor.newInstance("23333");
System.out.println(obj);

4、獲取方法

獲取某個Class對象的方法集合,主要有以下幾個方法:
getDeclaredMethods()方法返回類或接口聲明的所有方法,包括公共、保護、默認(包)訪問和私有方法,但不包括繼承的方法。

1
public Method[] getDeclaredMethods() throws SecurityException

getMethods()方法返回某個類的所有公用(public)方法,包括其繼承類的公用方法。

1
public Method[] getMethods() throws SecurityException

getMethod方法返回一個特定的方法,其中第一個參數爲方法名稱,後面的參數爲方法的參數對應Class的對象

1
public Method getMethod(String name, Class<?>... parameterTypes)

5、獲取構造器信息

獲取類構造器的用法與上述獲取方法的用法類似。主要是通過Class類的getConstructor方法得到Constructor類的一個實例,而Constructor類有一個newInstance方法可以創建一個對象實例:

1
public T newInstance(Object ... initargs)

此方法可以根據傳入的參數來調用對應的Constructor創建對象實例~

6、獲取類的成員變量(字段)信息

主要是這幾個方法,在此不再贅述:
getFiled: 訪問公有的成員變量
getDeclaredField:所有已聲明的成員變量。但不能得到其父類的成員變量
getFileds和getDeclaredFields用法同上(參照Method)

7、調用方法

當我們從類中獲取了一個方法後,我們就可以用invoke()方法來調用這個方法。invoke方法的原型爲:

1
2
3
public Object invoke(Object obj, Object... args)
throws IllegalAccessException, IllegalArgumentException,
InvocationTargetException

下面給一個例子:

public class test1 {
    public static void main(String[] args) throws IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException {
        Class<?> klass = methodClass.class;
        //創建methodClass的實例
        Object obj = klass.newInstance();
        //獲取methodClass類的add方法
        Method method = klass.getMethod("add",int.class,int.class);
        //調用method對應的方法 => add(1,4)
        Object result = method.invoke(obj,1,4);
        System.out.println(result);
    }
}
class methodClass {
    public final int fuck = 3;
    public int add(int a,int b) {
        return a+b;
    }
    public int sub(int a,int b) {
        return a+b;
    }
}

8、利用反射創建數組

數組在Java裏是比較特殊的一種類型,它可以賦值給一個Object Reference。下面我們看一看利用反射創建數組的例子:

	/**
	 * 用反射來創建數組
	 * @param args
	 */
	public static void main(String[] args) {
		try {
			Class<?> clazz = Class.forName("java.lang.String");
			Object array = Array.newInstance(clazz, 10);
			Array.set(array, 0, "Nuist");
			Array.set(array, 1, " is");
			Array.set(array, 2, " a");
			Array.set(array, 3, " good");
			Array.set(array, 4, " school.");
			
			for(int i = 0; i < 5; i ++) {
				if(null != Array.get(array, i) || !((String) Array.get(array, i)).equals("")) {
					System.out.print(Array.get(array, i).toString());
				}
			}
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
		}
	}
輸出結果:

其中的Array類爲java.lang.reflect.Array類。我們通過Array.newInstance()創建數組對象,它的原型是:
1
2
3
4
public static Object newInstance(Class<?> componentType, int length)
throws NegativeArraySizeException {
return newArray(componentType, length);
}

而newArray()方法是一個Native方法,它在Hotspot JVM裏的具體實現我們後邊再研究,這裏先把源碼貼出來

1
2
private static native Object newArray(Class<?> componentType, int length)
throws NegativeArraySizeException;
    望每天進步一點,再見

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