2012-06-18 39 views
45

Java中是否有類似於Callable接口的接口,它可以接受其調用方法的參數?是否有類似於Callable但具有參數的接口?

像這樣:

public interface MyCallable<V> { 
    V call(String s) throws Exception; 
} 

我寧願避免建立新的類型,如果已經存在的東西,我可以使用。還是有更好的策略讓多個客戶端實現並插入可調用的例程?

從這裏http://www.programmingforums.org/thread27905.html

+1

沒有,但看到像http://www.programmingforums.org/thread27905.html的東西。 –

回答

31

由於Java 8複製存在the java.util.function package一整套功能,接口等。你特別要求的是Function

在Java 8之前,沒有通用的內置接口,但有些庫提供了它。

例如Guava具有the Function<F,T> interface與方法T apply(F input)。它也使heavy use of that interface在幾個地方。

+0

上週我的同事也遇到了同樣的問題。我們的第一個明顯的選擇是使用Guava的功能。但是我們注意到apply()方法沒有拋出異常。這使它不適合我們的目的。不幸的是,我們不得不爲此創建自己的界面。至少它進入了全公司範圍內,以便重新使用。 –

+1

@FilipeFedalto:好吧,拋出異常和不拋出'Function'都可以。在Guava中'Function'的大多數用法很簡單:「轉換a-to-b」和「從bar對象獲取foo」的用途永遠不會(在一個健全的程序中)拋出一個檢查的異常(NPE,而未經檢查的異常是一個不同的故事)。這可能(可能)爲什麼Guava'Function'不會拋出異常。 –

+0

你想用它做什麼?像這樣的接口只有在實現它的時候才能讓你做的事情比直接實現更好。這對於'Function'來說並非總是如此,更不用說更復雜的野獸了。 –

1

答案不明確。嚴格地說,就是「爲了Callable接口的相同目的」,沒有。

也有類似的類,根據你的需要,它們可能會也可能不方便。其中之一是SwingWorker。然而,顧名思義,它是爲在Swing框架中使用而設計的。它可以用於其他目的,但這將是一個糟糕的設計選擇。

我最好的建議是使用擴展庫(Jakarta-Commons,Guava等)提供的一個,具體取決於您已經在系統中使用了哪些庫。

0

通常不需要參數,因爲該方法的構造函數中可以有任意數量的參數。

final int i = 5; 
final String word = "hello"; 

Future<String> future = service.submit(new Callable<String>() { 
    public String call() { 
     return word + i; 
    } 
}); 

在這個例子中iword已被使用,但你可以「通過」任意數量的參數。

+0

其實你是正確的,但只是爲了擴展,從許多角度來看,每次創建新的Callable對象都可能會被開銷和無用。示例 - 然後您通過單個元素逐個處理大集合,或者當您擁有某個Component時,您應該向他交付處理過程(以避免混合/混亂邏輯)。 – iMysak

+0

@iMysak要通過隊列之間的線程之間傳遞工作,您將創建相當多的對象(至少3我懷疑) –

+0

確實,從這一點你是完全正確:) – iMysak

7

起初它認爲這是通過一個接口完成的,但後來我發現它應該使用抽象類來完成。

我有這樣的方式解決它:


編輯:最近,我只是用這個:

public static abstract class callback1<T>{ 
     public abstract void run(T value); 
    } 

    public static abstract class callback2<T,J>{ 
     public abstract void run(T value,J value2); 
    } 

    public static abstract class callback3<T,J,Z>{ 
     public abstract void run(T value,J value2,Z value3); 
    } 


    public static abstract class callbackret1<R,T>{ 
     public abstract R run(T value); 
    } 

    public static abstract class callbackret2<R,T,J>{ 
     public abstract R run(T value,J value2); 
    } 

    public static abstract class callbackret3<R,T,J,Z>{ 
     public abstract R run(T value,J value2,Z value3); 
    } 

回調。的java

public abstract class CallBack<TRet,TArg> { 
    public abstract TRet call(TArg val); 
} 

定義方法:

class Sample2 
{ 
    CallBack<Void,String> cb; 
    void callcb(CallBack<Void,String> CB) 
    { 
    cb=CB; //save the callback 
    cb.call("yes!"); // call the callback 
    } 
} 

使用方法:

sample2.callcb(new CallBack<Void,String>(){ 
     @Override 
     public Void call(String val) { 
      // TODO Auto-generated method stub 
      return null; 
     } 
    }); 

兩個參數樣品:CallBack2.java

public abstract class CallBack2<TRet,TArg1,TArg2> { 
    public abstract TRet call(TArg1 val1,TArg2 val2); 
} 

注意,當你使用Void返回類型時,你必須使用return null; 所以這裏是一個修正,因爲通常回調不會返回任何值。

空隙作爲返回類型:SimpleCallBack.java

public abstract class SimpleCallBack<TArg> { 
    public abstract void call(TArg val); 
} 

空隙作爲返回類型2 ARGS:SimpleCallBack2.java

public abstract class SimpleCallBack<TArg1,TArg2> { 
    public abstract void call(TArg1 val1,TArg2 val2); 
} 

接口不是爲這是有用的。

接口允許多種類型匹配相同的類型。通過共享預定義的一組功能。

抽象類允許內部的空函數稍後完成。在擴展或實例化。

+0

我也認爲你的'CallBack'抽象類應該是一個接口,如果只是爲了允許多重繼承(快速例子:讓一個子類擴展你的一個類,並同時成爲一個CallBack)。是什麼讓你改變你的意見? –

+0

我有一種感覺,可以在將它作爲參數傳遞之前施放。抽象類也可以實現一個接口,你可以把它作爲參數,而不需要鑄造 –

+0

我仍然沒有看到使用抽象類的好處:當用於提供必須在子類中實現的方法時,簡化子類的開發。在這裏,您的抽象類中沒有任何代碼,只是抽象方法。因此,您可以改用接口。 –

4

我最近有同樣的要求。正如其他人所解釋的,許多庫提供了「功能」方法,但這些方法不會拋出異常。

的一些項目是如何提供的解決方案的一個例子是RxJava圖書館,它們使用如ActionX其中「X」是0 ... N,的參數傳遞給呼叫方法的數目的接口。他們甚至有一個可變參數界面,ActionN

我的當前方法是使用一個簡單的通用接口:

public interface Invoke<T,V> {  
    public T call(V data) throws Exception;  
// public T call(V... data) throws Exception;  
} 

第二種方法是在我的情況下,優選但它顯示出的是可怕的:在我的IDE「類型安全經由勢堆污染可變參數的參數數據」 ,這是另一個問題。

我在看的另一種方法是使用現有的接口,如java.util.concurrent.Callable不會拋出異常,並在我的實現包裝未經檢查的異常異常。

0

我剛剛有同樣的問題。你可以包裝任何方法來返回一個可調用的對象,並執行它的返回值。 即

main {  
    Callable<Integer> integerCallable = getIntegerCallable(400); 
    Future<Integer> future = executor.submit(integerCallable); 
} 

private Callable<Integer> getIntegerCallable(int n) { 
    return() -> { 
      try { 
       TimeUnit.SECONDS.sleep(n); 
       return 123; 
      } catch (InterruptedException e) { 
       throw new IllegalStateException("task interrupted", e); 
      } 
     }; 
} 
相關問題