1. 程式人生 > >javaweb-codereview 學習記錄-4

javaweb-codereview 學習記錄-4

反射java.lang.Runtime

之前在p牛的知識星球中也學過反射機制呼叫Runtime來執行命令時需要用getruntime來返回Runtime類的例項,因為Runtime類設計是單例模式,並且該類的構造方法是私有的,因此無法直接通過newinstance來例項化該類,因此除了通過getRuntime來返回類的例項來呼叫該類的方法外,還可以通過反射直接獲取該類的構造方法並且設定訪問屬性來例項化該類。

import sun.misc.IOUtils;

import java.io.InputStream;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;

public class reflect_runtime {
    private static Object cmd="calc";

    public static void main (String args[]) throws Exception {
        // 獲取Runtime類物件
        Class runtimeClass1 = Class.forName("java.lang.Runtime");

// 獲取構造方法
        Constructor constructor = runtimeClass1.getDeclaredConstructor();
        constructor.setAccessible(true);

// 建立Runtime類示例,等價於 Runtime rt = new Runtime();
        Object runtimeInstance = constructor.newInstance();

// 獲取Runtime的exec(String cmd)方法
        Method runtimeMethod = runtimeClass1.getMethod("exec", String.class);

// 呼叫exec方法,等價於 rt.exec(cmd);
        Process process = (Process) runtimeMethod.invoke(runtimeInstance, cmd);



    }

}

上面的程式碼註釋已經解釋的非常清楚了,此時可以通過class型別物件的getDeclaredConstructor()返回類的無引數構造方法,然後再通過setAccessible(true)來修改該構造方法的訪問屬性,從而方便接下來通過該構造器來newInstance該類的例項。

 而這裡getRuntime返回的就是該類的例項

 

 

getConstructor和getDeclareConstructor都可以獲得類的構造方法,區別是後者可以拿到類的私有構造方法,而前者不行,所以一般來說要拿到類的構造方法都用前者,當然如果一個類有多個構造方法,那麼取其構造方法時可以加上其方法的入口引數型別,和反射呼叫函式較為類似,那麼getDeclareConstructors就可以獲得類的所有的建構函式,返回為陣列,就可以進行更多操作。

反射呼叫類方法

這一點在p牛的知識星球中也有,通過class型別的物件來呼叫類的方法,當然這裡也有兩種方式,getMethod和getDeclareMethod都能夠獲取到類成員方法,區別在於getMethod只能獲取到當前類和父類的所有有許可權的方法(如:public修飾的方法),而getDeclareMethod能獲取到當前類的所有成員方法(不包含父類)。

通過Method.invoke()反射呼叫方法時,invoke函式的第一個引數一般為反射呼叫的類的例項,第二個開始即為傳入的引數,但是如果呼叫的是類的靜態方法,則第一個引數可以為null,因為呼叫類的靜態方法不需要例項化該類。

反射呼叫成員變數

通過getDeclaredField就能夠拿到該類所有的成員變數。

getFieldgetDeclaredField的區別同getMethodgetDeclaredMethod

 獲取成員變數值:

Object obj = field.get(類例項物件);
修改成員變數值:
field.set(類例項物件, 修改後的值);

同理這裡修改類似private修飾的變數時也可以使用setAccessible來修改訪問