I have missed a problem with the Java Generic type
public class MyTest {
@Test
public void test1() throws Exception {
List<Integer> list = getMapInstance();
}
public static <T extends Map<Object, Object>> T getMapInstance() {
T t = (T) new HashMap<>();
return t;
}
}
In the code, I assign a T (which extends Map<Object, Object>) to a List, I think it will be intercepted by compile-time type checking. but it successfully complied and when I run it, it throws a ClassCastException
//the bytecode of test1
0 invokestatic #10 <org/example/BugTest.getMapInstance : ()Ljava/util/Map;>
3 checkcast #11 <java/util/List>
6 astore_1
7 return
My JDK version is 11 and 17
I want to know why this code compiles successfully, please
I have tried to create a class which implements interface List and Map, but the remove method of List and Map will conflict
boolean remove(Object o);
V remove(Object key);
List<Integer>
andMap<Object, Object>
I guessT
must be inferred to be the intersection of those two types? I have to admit, I would not have expected that! – NewsmongerList
toMap
and vice versa is because they're both interfaces - there could be a class that implements both. Only if the compiler can detect that the cast is impossible will there be a compiler error. The compiler can only detect it if one of the two is a final class (e.g. you cannot cast aList
toString
or vice versa), or if both are classes that are in different hierarchical class trees (e.g. you cannot cast anInteger
toString
or vice versa). – RamonX
andY
there could be a classA implements X, Y
- and this is all the Java Compiler verifies. The Java Compiler specifically does not examine the two interface for conflicting method definitions (like theremove(Object)
method in theList
andMap
interfaces) – Hoke