Duplicate :
|
|
Relates :
|
|
Relates :
|
This program should not compile: class Test<X extends Integer & Runnable> { private X x = null; public X getX() { return x; } public static <T extends Integer & Runnable> Test<T> factory() { return new Test<T>(); } public String toString() { return "Test("+x+")"; } public static void main(String[] args) { Test<?> t = Test.factory(); Integer i = t.getX(); Runnable r = t.getX(); System.out.println("Peter won't be happy: "+t); } } The call to Test.factory should infer Object for T and thus fail. Object is not a subtype of Integer nor Runnable. However I discovered that javac is really sensitive to little differences in the source code; consider the following source: class Test<V> { <T extends Integer & Runnable> Test<T> m() { return null; } void test() { Test<?> c1 = m(); //1 - should compile Test<? extends String> c2 = m(); //2 - shouldn't compile Test<? super String> c3 = m(); //3 - shoudln't compile } } Surprisingly, javac rejects (1), which is wrong and, worse, diagnostics for both (2) and (3) reveal that something weird is going on: Test3.java:6: incompatible types; inferred type argument(s) java.lang.Object do not conform to bounds of type variable(s) T found : <T>Test<T> required: Test<?> Test<?> c1 = m(); ^ Test3.java:7: incompatible types; inferred type argument(s) java.lang.String do not conform to bounds of type variable(s) T found : <T>Test<T> required: Test<? extends java.lang.String> Test<? extends String> c2 = m(); //2 - shoudln't compile ^ Test3.java:8: incompatible types; inferred type argument(s) java.lang.Object do not conform to bounds of type variable(s) T found : <T>Test<T> required: Test<? super java.lang.String> Test<? super String> c3 = m(); //3 - shoudln't compile ^ 3 errors The inferred types are all wrong: (1) Object instead of Integer&Runnable (2) String instead of error (glb(String,Integer,Runnable) (3) Object instead of Integer&Runnable
|