java允许使用功能接口作为方法吗?

时间:2012-11-01 08:54:57

标签: java lambda closures java-8

使用新的java lambdas和功能接口的概念,是否可以将这些功能接口视为方法?

interface Func { void execute(int i); }

void call(Func f)
{
    f(1); //instead of f.execute(1);
}

我发现了很多关于实际lambda表达式语法的信息,但没有提到这一点。

2 个答案:

答案 0 :(得分:15)

您的主张

您提出的建议已在lambda-dev邮件列表中讨论过:

http://mail.openjdk.java.net/pipermail/lambda-dev/2012-February/004518.html

由于与解析器/编译器产生的歧义相关的各种问题,它主要被拒绝。或者在Brian Goetz的条款中:

  

我认为,最终,这只是对功能界面而不是功能类型的承诺感到不适,并试图向一个多余的中间地带进行倒退。我不认为这提供了足够令人信服的好处。

如果你觉得这样的“wishy-washy”功能仍然会增加Java语言的价值,你可以在lambda邮件列表中再试一次运气,也许有令人信服的论据: - )

另一种选择

这可能,但可能不像JavaScript中的示例语法那样优雅。根据最新的state-of-the-lambda by Brian Goetz,将会有章节

中提到的方法参考
  

8方法参考

     

[...]

     

9种方法参考

     

[...]实际上有三种不同的方法参考,每种方法参考   语法略有不同:

     
      
  • 静态方法
  •   
  • 特定对象的实例方法
  •   
  • 特定类型的任意对象的实例方法
  •   

事实上,你的例子必须按照这些方式进行改写:

interface Func { void execute(int i); }

void call(Block<Integer> block)
{
    block.run(1); //instead of f.execute(1);
}

您现在可以传递对该execute方法的引用:

// Disclaimer: I didn't check this against a JDK8 compiler...
Func f = (i) -> { ; }; // Empty sample implementation
call(f::execute)

换句话说,“功能”样式将在您的调用方法的声明站点实现,而不是在使用站点实现。但与JavaScript一样,use-site不必知道Func中具体方法的名称。对于返回值Block的方法,它只能接受void,对于返回值的方法,它只能接受Callable

请注意,在JDK的Mercurial存储库中,事情已经发生了变化。你不会再找到run(),正如lambda的状态所提到的那样。其他有趣的类型可以在java.util.functions包中找到:

http://hg.openjdk.java.net/lambda/lambda/jdk/file/tip/src/share/classes/java/util/function

答案 1 :(得分:2)

如果我正确理解你的问题,你暗示给定的函数接口Mapper声明如下

interface Mapper<T,U> {
   public U map(T t);
}

如果我使用lambda表达式实现此功能接口,如下所示:

Mapper<Integer,String> itoa = (n) -> String.valueOf(n);

您想按如下方式调用函数接口:

String val = itoa(10); //would yield "10"

而不是今天:

String val = itoa.map(10);

我想,第一次调用是第二次调用的语法糖。

我没有在任何文档或邮件列表中读到他们计划在即将发布的JDK版本中提供此功能。但我想你可以在lambda mailing list中提出这个问题。我没有看到为什么无法实施这个原因。