60

Java中是否有类似于接口的Callable接口,可以接受其调用方法的参数?

像这样:

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

如果已经存在可以使用的东西,我宁愿避免创建新类型。或者有没有更好的策略让多个客户端实现并插入一个可调用的例程?

从这里复制http://www.programmingforums.org/thread27905.html

4

8 回答 8

51

从 Java 8 开始,包中java.util.function一整套类似函数的接口。您要特别要求的是 simple Function

在 Java 8 之前,没有通用的内置接口,但一些库提供了它。

例如Guava具有与方法Function<F,T>接口T apply(F input)。它还在几个地方大量使用了该接口

于 2012-06-18T13:27:44.427 回答
9

起初它认为这是通过接口完成的,但后来我发现它应该使用抽象类来完成。

我已经这样解决了:


编辑:最近我只是用这个:

    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;所以这里有一个变体来解决这个问题,因为通常回调不返回任何值。

void 作为返回类型:SimpleCallBack.java

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

void 作为返回类型 2 参数:SimpleCallBack2.java

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

接口对此没有用。

接口允许多个类型匹配相同的类型。通过共享一组预定义的功能。

抽象类允许稍后完成其中的空函数。在扩展或实例化。

于 2013-08-31T08:32:18.787 回答
5

我最近也有同样的要求。正如其他人所解释的那样,许多库确实提供了“功能”方法,但这些方法不会引发异常。

一些项目如何提供解决方案的一个示例是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 ,并在我的实现中将异常包装在未经检查的异常中。

于 2013-12-15T13:10:30.447 回答
3

从 Java 1.8 开始就有了一个Supplier<T>接口。它有一个get()方法,而call()不是声明任何抛出的异常。

于 2018-03-23T14:59:21.263 回答
1

答案是模棱两可的。严格来说,就是“同Callable接口一样”,是没有的。

有类似的课程,根据您的需要,它们可能方便也可能不方便。其中之一是SwingWorker。但是,顾名思义,它是为在 Swing 框架中使用而设计的。它可以用于其他目的,但这将是一个糟糕的设计选择。

我最好的建议是使用扩展库(Jakarta-Commons、Guava 等)提供的扩展库,具体取决于您系统中已经使用的库。

于 2012-06-18T13:33:11.083 回答
0

通常不需要参数,因为该方法在其构造函数中可以有任意数量的参数。

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

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

在此示例中iword已使用,但您可以“传递”任意数量的参数。

于 2012-06-18T14:00:24.097 回答
0

我只是有同样的问题。您可以包装任何方法以返回可调用对象,并执行它的返回值。IE

 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);
            }
        };
}
于 2017-01-12T09:39:46.780 回答
0

像这样定义一个接口:

interface MyFunction<I, O> {
    O call(I input);
}

定义一个方法:

void getOrderData(final Function<JSONArray, Void> func){
    ...
    JSONArray json = getJSONArray();
    if(func!=null) func.call(json);           
}

使用示例:

//call getOrderData somewhere in your code
getOrderData(new Function<JSONArray, Void>() {
        @Override
        public Void call(JSONArray input) {
            parseJSON(input);                
            return null;
        }
});
于 2019-06-21T14:50:08.047 回答