在Java中,是否可以将某个对象(即String)与要调用的函数关联起来?
我有两个相似的菜单,两个都有一个onClickListener,代码如下:
if (item.id==0) {
doSomeFunction(argument);
}
else if (item.id==1) {
doSomeOtherFunction();
}
else if (item.id==2) {
doStuff(arg2);
}
else {
}
我想要一个对象(即Hashtable),它允许我定义“item.id” - >之间的关联。 “要执行的代码”。
示例:
0 -> doSomeFunction(argument);
1 -> doSomeOtherFunction();
2 -> doStuff(arg2);
因此,我可以跳过这些条件并只执行为给定item.id存储的函数的函数调用。
例如,使用Lisp,我可以将item.id与函数关联,然后使用Lisp的“funcall”来调用该函数。
在Java中有没有一种标准的方法可以做这样的事情?
是否有其他解决方案可以跳过条件?
请注意,被叫函数可能需要接收参数。
感谢。
答案 0 :(得分:3)
由于您的函数看起来不需要返回任何值,因此您可以将每个ID键与调用所需方法的Runnable
对象相关联。例如:
Map<Integer, Runnable> map = ...;
map.put(0, new Runnable() {
public void run() {
doSomeFunction();
}
});
map.get(0).run();
如果您需要方法能够返回值,则可以使用Callable
而不是Runnable
。您也可以创建自己的类似界面,并在需要时使用它。
目前在Java中,必须使用单个抽象方法(例如Runnable
)对类的实例进行此类操作。 Java 7或8(取决于他们决定如何继续)将添加lambda表达式和方法引用,我认为这是你真正想要的。方法参考将允许您执行类似这样的操作(使用Map<Integer, Runnable>
,如上所述)。
map.put(0, Foo#doSomeFunction());
修改强>:
您的更新表明其中一些方法需要传递参数。但是,你似乎要求两件不同的事情。在您声明映射的示例中
0 -> doSomeFunction(argument);
1 -> doSomeOtherFunction();
2 -> doStuff(arg2);
指定了参数,表明它们是您声明映射时可用的值,或者它们是类中的字段或某些字段。在任何一种情况下,您都可以在创建Runnable
:
new Runnable() {
public void run() {
doSomeFunction(argument);
}
}
此处,argument
要么必须是字段,要么声明为final
。
另一方面,如果在创建映射时没有对参数的引用,则必须创建一个所有方法调用可以共享的一致接口。例如,可以用于您的示例的最不常见的接口将是声明两个参数和void
返回的接口:
public interface CustomRunnable<T,G> {
public void run(T arg1, G arg2);
}
然后你可以:
map.put(0, new CustomRunnable<Foo,Bar>() {
public void run(Foo arg1, Bar arg2) {
doSomeFunction(arg1);
}
});
map.put(1, new CustomRunnable<Foo,Bar>() {
public void run(Foo arg1, Bar arg2) {
doSomeOtherFunction();
}
});
map.put(2, new CustomRunnable<Foo,Bar>() {
public void run(Foo arg1, Bar arg2) {
doStuff(arg2);
}
});
每个CustomRunnable
仅使用它需要的参数(如果有的话)。然后你可以这样打电话:
map.get(item.id).run(argument, arg2);
显然,这变得非常难看,但在这种情况下,这几乎就是你必须要做的事情。
答案 1 :(得分:1)
是的,有几种方法可以做到这一点。一个例子是匿名实现接口并将其存储在HashMap中,如下所示:
public class MyListeningClass
{
...
public interface MyEventHandler
{
public void handle(String myParam);
}
private HashMap<ItemType, MyEventHandler> eventHandlers= new HashMap<ItemType, MyEventHandler>();
initItems()
{
//do for each item
eventHandlers.put(item1, new MyEventHandler(){public void handle(String myParam){
//do whatever I want to
}});
}
myListeningMethod(ItemType item)
{
eventHandlers.get(item).handle("a parameter");
}
}
答案 2 :(得分:1)
通常要做的是在每个菜单项上添加一个不同的动作侦听器(命令),实现为一个简短的匿名内部类。不幸的是,语法目前很冗长,它无助于启动时间,但它仍然是最好的方法。
您没有说出您正在使用的库。 onClickListener
不是Swing,但如果您使用的是Swing,则需要JMenuItem.addActionListener
。
答案 3 :(得分:0)
Java Swing的回答方式是Action类。基本上它遵循命令模式......