Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Java 8 closures and type recognition

Tags:

java

closures

I'm testing the new closure features of Java 8; I'm wondering why this piece of code

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(); }
}

gives the error: both method z(IFA) in Test8 and method z(IFB) in Test8 match error on z invocation in the run method

Isn't the compiler able to detect that the forceA invocation forces x to be of type A and thus the correct z to use is z(IFA fun) ?

(a similar function is legal in C# using delegate; is there a way to get the same result in Java 8? )

like image 215
Vor Avatar asked Mar 01 '13 23:03

Vor


1 Answers

Java 8 is still a work in progress. The latest spec does allow your code to work. The compiler implementation should catch up soon.

Nevertheless, this kind of overloading is not a good style. We have signatures

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

then when javac sees

    z( arg->{ block } )

it's not apparent which z() applies. Extra work must be done (by compiling block) to pick one.

We don't really care about how difficult it is to javac. The real issue is, when a human sees that code, the human has to dig deeper to understand which z() is referred to. Not very readable.

As a rule of thumb, avoid overloading a method with functional interfaces of the same arity. Different arities are fine, there's no problem to disambiguate, for human or javac

    z( arg->{...} )

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

Another form of overloading is also blessed by the designers (Dan Smith etc) - same arity, same parameter types, but different return types

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

but I think it is pretty confusing too and I would avoid it.

like image 98
irreputable Avatar answered Oct 14 '22 00:10

irreputable