Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Type checking broken on matching capture with upper bound?

Create a class like

public class Play {
    public static void main(String[] args) throws Exception {
        outer(Integer.class, inner("abc"));
    }

    static <C> void outer(Class<C> c, List<? super C> s){
    }

    static <C> List<C> inner(C c) {
        return null;
    }
}

and it compiles in Java 8! (Both in Eclipse 4.5 and JDK1.8_25) https://ideone.com/Q9JLHP

In Eclipse, all the bounds are inferred correctly, but how could outer's capture Supplier<? super Integer> ever been satisfied by the argument Supplier<String>??

Edit: clarified this is Java 8-specific and made the example less confusing.

like image 797
billc.cn Avatar asked Aug 25 '15 16:08

billc.cn


2 Answers

inner("abc") can, at the compiler's discretion, be interpreted as a Supplier of any supertype of String. -- for example,

Supplier<Object> inner = inner("abc");

works just fine, because "abc" is also an Object. That's what's happening here: inner is returning you a Supplier<Object>.

like image 183
Louis Wasserman Avatar answered Nov 09 '22 23:11

Louis Wasserman


Inference on inner requires that C is a supertype of Integer and String.

What is C exactly? That is a complicated story. Both Integer and String are Object, of course. But both are Serializable too! and Comparable<?> too....

In the end, it doesn't matter much; all we need to know is that it is a "least upper bound" of String and Integer, in whatever way it is defined.

like image 22
ZhongYu Avatar answered Nov 10 '22 00:11

ZhongYu