Why the <T extend Map> could be assigned to a List
Asked Answered
C

0

7

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);
Conk answered 11/5 at 8:13 Comment(4)
Interesting; great question! Seeing as it's totally possible for a single class to implement both List<Integer> and Map<Object, Object> I guess T must be inferred to be the intersection of those two types? I have to admit, I would not have expected that!Newsmonger
if I create a Class which implements List and Map interface, this code will run successfully? That is too unbelievableConk
The reason why the compiler allows casting List to Map 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 a List to String or vice versa), or if both are classes that are in different hierarchical class trees (e.g. you cannot cast an Integer to String or vice versa).Ramon
For any two interfaces X and Y there could be a class A 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 the remove(Object) method in the List and Map interfaces)Hoke

© 2022 - 2024 — McMap. All rights reserved.