2010-09-13 90 views
0

在Java中,是否可以将某个对象(即字符串)与要调用的函数相关联?为给定值定义回调函数

我有两个相似的菜单和都有一个onClickListener有一些像这样的代码:

if (item.id==0) { 
doSomeFunction(argument); 
} 
else if (item.id==1) { 
doSomeOtherFunction(); 
} 
else if (item.id==2) { 
doStuff(arg2); 
} 
else { 

} 

我只是想有一个对象(即哈希表),让我到项目之间的”定义的关联。 id“ - >”要执行的代码“。

实施例:

0 -> doSomeFunction(argument); 
1 -> doSomeOtherFunction(); 
2 -> doStuff(arg2); 

其结果,我可以跳过这些条件语句和刚刚执行存储对于给定的item.id.的功能的函数呼叫

例如,在Lisp中,我可以将item.id与一个函数相关联,然后使用Lisp的“funcall”来调用该函数。

有没有一种标准的方式在Java中做这样的事情?

是否有替代解决方案跳过条件?

请注意,被调用函数可能需要接收参数。

谢谢。

回答

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); 

参数的映射,这表明它们是可在任何时间值的例子中,你声明的映射或他们是在课堂或一些这样的领域。

new Runnable() { 
    public void run() { 
    doSomeFunction(argument); 
    } 
} 

这里,argument要么需要一个字段或声明final:在任何情况下,当你创建Runnable你可以申报。

另一方面,如果在创建映射时没有对参数的引用,则必须创建一个可供所有方法调用共享的一致接口。例如,可以为您的样品工作,最不常见的接口将是一个定义了两个参数,一个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只使用arguments它需要,如果有的话。那么你可以这样做:

map.get(item.id).run(argument, arg2); 

显然,这是越来越丑,但它几乎是你在这种情况下必须做的。

+0

+1为有趣的例子,并注意到Java 7/8中可能的Lambdas。 – MyNameIsZero 2010-09-16 00:37:49

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"); 
    } 
} 
0

的Java Swing的方式为这是Action类。基本上它遵循命令模式...

1

通常要做的是在每个菜单项上添加一个不同的动作监听器(命令),作为一个短的匿名内部类实现。不幸的是,语法目前是冗长的,并不能帮助启动时间,但它仍然是最好的方法。

你不说你正在使用什么库。 onClickListener不是Swing,但如果您使用Swing,则需要JMenuItem.addActionListener

+0

我使用的库是属于“Android”(移动操作系统)的库。谢谢。 – MyNameIsZero 2010-09-15 12:16:54