[英]In Java, I want to call a method on an object by the name of 'foo', but 'foo' is a string. How do I get around this?
我有一個名為“ foo”的對象(Object foo = new Object())。 我想在另一個方法中調用該對象,在該方法中,我在簽名中傳遞一個帶有該對象名稱的字符串。 如何通過使用代表對象名稱的字符串來調用該對象?
我收到找不到符號錯誤。
這是一些代碼:
//from main method
Object foo = new Object();
Monitor monitor = new Monitor();
//end main method
class Monitor {
public Monitor() {
Manager manager = new Manager();
}
//IMPORTANT - info.objectName is user input, and for this example it is "foo"
public void processArgument(Instruction info) {
if (info.command == "read") int value = manager.read(info.objectName);
}
}
class Manager {
public int read(String obj) {
return obj.getRead();
}
}
class Object {
private int value;
public int getRead() {return value;}
}
我希望這是有道理的,雖然我不是很擅長,但是我需要一些幫助。 這是針對具有嚴格的反代碼共享策略的類,因此我嘗試將其盡可能抽象化。
Java或JVM中對此不支持。
給定MyCustomObject xxx = new MyCustomObject();
在給定String s = "xxx";
的情況下,無法實際調用xxx
上的任何方法,該方法是對Java中MyCustomObject
類型的實例的引用String s = "xxx";
。 因為無法在JVM中搜索名為xxx
的引用。 沒有一種方法可以讓您在給定String
查找參考xxx
。
Java反射:通過輸入名稱來獲取給定類的實例? 如果無法通過引用名稱找到它,則無法在其上調用任何方法!
您可以自己將該引用存儲在某種Map<String, T>
結構中,然后在周圍傳遞該結構並自己進行搜索,但這並不是JVM或語言本身所內置的。 強制執行此操作幾乎是不可能的,它會導致與某些static
數據的緊密耦合,而其他許多不良的設計問題也將導致很多麻煩。
如果要調用名稱為“ foo”的方法,
Class classOfFoo = FooClass.class;
FooClass obj = new FooClass(); //Or may be you have your own object.
classOfFoo.getDeclaredMethod("foo",fooParameter.class).invoke(obj,fooParametersObj);
您可能想看看反射API。
有兩種本機執行此操作的方法,另一種是本機執行的方法。
您擁有的是選項1,而且大多數情況下都是正確的,只是使用了錯誤的比較方式。 比較你的
public void processArgument(Instruction info) {
// this is bad - uses reference comparison
if (info.command == "read")
int value = manager.read(info.objectName);
}
與推薦
public void processArgument(Instruction info) {
// this is good - actually compares the values
if (info.command.equals("read"))
int value = manager.read(info.objectName);
}
有些人認為這樣做更好,因為如果info.command
為null,則不會引發異常。 我個人不喜歡這樣,因為我寧願得到例外,但是許多人主張這樣做,而且他們有完全正當的理由。
public void processArgument(Instruction info) {
// "read" can never be null, so no null pointer exception here
if ("read".equals(info) )
int value = manager.read(info.objectName);
}
當然,隨着您添加更多行為,您只需添加更多if語句。
在Java 7中,您可以執行以下操作:
public void processArgument(Instruction info) {
switch(info.command) {
case "read": manager.read(info.objectName); break;
case "write": manager.write(info.objectName); break;
default: throw new IllegalArgumentException("Command " + info.command + " not supported");
}
}
另一種選擇是使用利用匿名類的Map,如下所示:
// define this somewhere
abstract class Functor {
Manager m;
Functor(Manager m) { this.m = m; }
void execute(Instruction info);
}
// somewhere you have access to
Map<String,Functor> funcs = new HashMap<String,Functor>();
// add this to a static block, or constructor, depending
funcs.put("read", new Functor(manager) {
public void execute(Instruction info) { m.read(info.objectName); }
});
funcs.put("write", new Functor(manager) {
public void execute(Instruction info) { m.write(info.objectName); }
}
然后當你打電話給你的論點時
public void processArgument(Instruction info) {
Functor f = funcs.get(info.command);
if(f == null) throw new IllegalArgumentException("Operation " + info.command + " not supported");
f.execute(info);
}
像薩加爾·達巴斯(SagarDabas)在他的帖子中概述的那樣,使用反思。 請注意,這可能需要特殊的訪問權限,並且不會為您提供更靈活的正確性選項。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.