通用功能接口

6

我遇到了一些Lambda表达式的问题。
我试图使用Lambda表达式和函数式接口来创建一个方法,接受函数式接口和一些参数并执行该函数。

以下是我的代码:

@FunctionalInterface
interface TwoArgumentFunction {
    public <T, K, V> T doJob(K arg1, V arg2);
} //I know I've ommited return value in that case


class SomeClass {
<T, K, V> T runLongAction(TwoArgumentFunction action, K arg1, V arg2){
    SwingWorker<T, Void> worker = new SwingWorker<T, Void>(){

        @Override
        protected T doInBackground() throws Exception {
            {... some code ... }
            return action.doJob(arg1, arg2);
        }
        @Override
        protected void done(){
            {... some code ... }
        }

    };
    worker.execute();
    try {
        return worker.get();
    } catch (InterruptedException | ExecutionException e) {
        {... some code ... }
    }
}


void mainInvoke(ArgType1 arg1, ArgType2 arg2){
    runLongAction((arg1, arg2) -> doSomething(arg1, arg2), arg1, arg2);
}

我遇到了错误:

方法runLongAction((arg1, arg2) -> {}, ArgType1, ArgType2)对于类型SomeClass是未定义的。

我甚至尝试将lambda表达式强制转换为TwoArgumentFunction,但是我得到了以下错误:

非法的lambda表达式:类型为TwoArgumentFunction的方法doJob是泛型的

使用匿名类而不是lambda表达式可以正常工作,这是我找到的最简单的解决方法。


1
TwoArgumentFunctionjava.util.function.BiFunction 是相同的吗? - gontard
3个回答

10

请尝试以下方法:

  @FunctionalInterface
  interface TwoArgumentFunction<T, K, V> {
     T doJob(K arg1, V arg2);
  } //I know I've ommited return value in that case

  public <T, K, V> T runLongAction(final TwoArgumentFunction<? extends T, ? super K, ? super V> action, final K arg1, final V arg2) {
    return action.doJob(arg1, arg2);
  }

  private void test() {
    final String a = "A";
    final Long b = 1L;
    this.runLongAction((ta, tb) -> {return 1;}, a, b);
  }

你将泛型放到了方法上,而我把它放到了接口上。我还添加了? super? extends(但即使没有它,这也可以工作)。

如果你不知道并且需要的话,你也可以在lambda表达式中指定类型:

this.runLongAction((String ta, Long tb) -> {return 1;}, a, b);

好的,我犯了三个错误。我在lambda和周围的方法中使用了相同的变量名称,在接口中使用了泛型方法,并在lambda中省略了返回值。即使我不需要它们(因为我的doSomething是void类型),似乎也是必需的。感谢您的帮助。 - Kaskader

1

在Java 8中已经存在的接口无需您创建新的接口。您应该使用'BIFunction'接口,该接口具有一个方法'R apply(T t, U u))'。


你说得没错,但这只是简单的代码,我在实际应用中无法使用BiFunction。 - Kaskader

0

我没有看到doSomething()方法

但这对我有效

void mainInvoke(ArgType1 arg1, ArgType2 arg2){
    runLongAction(this::doSomething, arg1, arg2);
}

private <T, K, V> T doSomething(K arg1, V arg2) {
  // TODO Auto-generated method stub
  return null;
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接