6

我正在测试 Java 8 的新闭包特性;我想知道为什么这段代码

public class Test8 {
    private class A { int a;}
    private class B { int b;}    
    interface IFA { void ifa(A param); }
    interface IFB { void ifb(B param); }
    private void forceA(A expr) {  }    
    private void z(IFA fun) { System.out.println( "A"); fun.ifa( new A() ); }
    private void z(IFB fun) { System.out.println( "B"); fun.ifb( new B() ); }    

    public void run() {
        z( x -> forceA(x) );
    }
    public static void main(String args[]) {   new Test8().run(); }
}

给出错误: both method z(IFA) in Test8 and method z(IFB) in Test8 match error在运行方法中的 z 调用

编译器是否无法检测到forceA调用强制 x 为 A 类型,因此正确使用的 z 是z(IFA fun)

(类似的函数在 C# 中使用委托是合法的;有没有办法在 Java 8 中获得相同的结果?)

4

2 回答 2

3

Java 8 仍在进行中。最新的规范确实允许您的代码工作。编译器实现应该很快就会赶上。

然而,这种重载并不是一种好的风格。我们有签名

    z( A->void )
    z( B->void )

然后当 javac 看到

    z( arg->{ block } )

不清楚哪个z()适用。必须做额外的工作(通过编译块)来选择一个。

我们并不真正关心 javac 的难度。真正的问题是,当人们看到该代码时,人们必须深入挖掘以了解z()所引用的代码。不太可读。

作为经验法则,避免重载具有相同数量的功能接口的方法。不同的arities都很好,消除歧义没有问题,对于人类或javac

    z( arg->{...} )

    z( (arg1,arg2)->{...} )

设计者(Dan Smith 等)也祝福了另一种形式的重载 - 相同的数量,相同的参数类型,但不同的返回类型

    z( X->R1 )
    z( X->R2 )

但我认为这也很混乱,我会避免它。

于 2013-03-02T01:16:16.073 回答
0

lambda 的主体不用于确定其类型。喜欢方法。我想方法参考可能有效。但是euw,超载。

于 2013-03-02T01:06:22.217 回答