From Gossip@Openhome

Java Gossip: 呼叫方法

如果您會動態載入類別並使用有參數的建構函式(參考 生成物件),則動態呼叫所生成物件之方法並不是難事,直接以實例說明,首先寫一個 Student類別:
  • Student.java
package onlyfun.caterpillar;

public class Student {
private String name;
private int score;

public Student() {
name = "N/A";
}

public Student(String name, int score) {
this.name = name;
this.score = score;
}

public void setName(String name) {
this.name = name;
}

public void setScore(int score) {
this.score = score;
}

public String getName() {
return name;
}

public int getScore() {
return score;
}

public void showData() {
System.out.println("name: " + name);
System.out.println("score: " + score);
}
}

再來寫個動態載入與呼叫方法的程式:
  • InvokeMethod.java
package onlyfun.caterpillar;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

public class InvokeMethodDemo {
public static void main(String[] args) {
try {
Class c = Class.forName(args[0]);
Object targetObj = c.newInstance();

Class[] param1 = {String.class};
Method setName = c.getMethod("setName", param1);

Object[] paramObjs1 = {"caterpillar"};
setName.invoke(targetObj, paramObjs1);


Class[] param2 = {Integer.TYPE};
Method setScore =
c.getMethod("setScore", param2);

Object[] paramObjs2 = {new Integer(90)};
setScore.invoke(targetObj, paramObjs2);

Method showData =
c.getMethod("showData", new Class[0]);
showData.invoke(targetObj, new Object[0]);

} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (SecurityException e) {
e.printStackTrace();
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
}
}
}

執行結果:
java InvokeMethodDemo onlyfun.caterpillar.Student
name: caterpillar
score: 90


在很少的情況下,您會需要突破Java的存取限制來呼叫受護的或私有的方法(例如您拿到一個組件,但您沒法修改它的原始碼,而您又一定要呼叫某個私有方法),這時候您可以使用反射機制來達到您的目的,一個存取私有方法的例子如下:
Method privateTest =
            c.getDeclaredMethod("privateTest", new Class[0]);
privateTest.setAccessible(true);
privateTest.invoke(targetObj, new Object[0]);
 
所以在Java中即使宣告為私有方法或成員,仍可以透過反射機制存取私有方法,要突破權限仍是可以的,但該如何用則取決於您自己。