sndyuk
sndyuk

Reputation: 2770

Illogical type Inference in Java8

I would like to know why the code ☆2 can be compiled with Java8:

public class Sandbox {

    public static void main(String[] args) {

        // ☆1: NG: Type mismatch: cannot convert from Object to String
        String res0 = IList.nil().head(); 

        // ☆2: OK: I don't know why it's OK.
        String res1 = IList.nil().head2();
    }

    static class IList<E> {

        static <Z> IList<Z> nil() {
            return null;
        }

        E head() {
            return null;
        }

        <TeE extends E> TeE head2() {
            return null;
        }
    }
}

Note: Also I am wondering that the JEP(http://openjdk.java.net/jeps/101)'s goal.

Upvotes: 1

Views: 136

Answers (2)

Simon Forsberg
Simon Forsberg

Reputation: 13331

This has nothing to do with Java 8. #2 also compiles on Java 7.

I think what it all boils down to is <TeE extends E> in your head2 method. Java sees that you're expecting a String in return, because of this line:

String res1 = IList.nil().head2();

Therefore it concludes that, ah, in that case I'll return a String for now - because String extends Object, so the <TeE extends E> is valid.

This works thanks to the fact you're returning null inside the method. If you would not do that, an error would occur within that method. And as null can be assigned to everything but primitives, this code is OK.

Upvotes: 4

Louis Wasserman
Louis Wasserman

Reputation: 198033

Java typically defaults generics to their outer bound. In this particular case it types as

 String res1 = IList.<Object>nil().<String>head2();

...because only the outermost method call "knows" the desired result type.

Upvotes: 4

Related Questions