2010-09-13 84 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