简体   繁体   中英

Hierarchy information for generics in Java

I understand that while List< Integer> is not a subtype of List< Number> , but it is subtype of List<? extends Number> List<? extends Number> .

But as Java uses concept of type erasure to implement generics, meaning that we ultimately have single class for all representations, and hence we don't have any class hierarchy defined for such classes in bytecode, then how does Java establishes this hierarchy?

Java is not bytecode, it compiles to bytecode. It is precisely because of this that it can be made a more powerful language than bytecode.

The Java Language is specified in the Java Language Specifications . There will be lots of things in this spec that the JVM doesn't know about. Parameterised types being one of them. But that's fine, because it is the job of the compiler to translate Java source code to something that the JVM can understand. In the case of generic types, this means erasing the generic parameters, and adding lots of casts.

hence we don't have any class hierarchy defined for such classes in bytecode, then how does Java establishes this hierarchy?

To the Java compiler, List<? extends Object> List<? extends Object> and List<Object> are different types. This is necessary to enforce type-safety. Does it matter that the JVM thinks they are the same? Not really, because the compiler is a standalone program itself. It can stop your code from compiling/allow your code to compile without "consulting" the JVM. The compiler knows that List< Number> is a subtype of List<? extends Number> List<? extends Number> . It knows the type hierarchy, so it can enforce it at compile time.

What about runtime then? As you'd imagine, this type hierarchy of generics cannot be enforced at runtime, because the JVM doesn't know about generics. eg this doesn't throw an exception:

public class Main {

    public static ArrayList<Object> list;

    public static void main(String[] args) throws NoSuchFieldException, IllegalAccessException {
        ArrayList<String> list = new ArrayList<>();
        // here we are doing the equivalent of:
        // Main.list = list;
        // using reflection (hence at runtime)
        Main.class.getField("list").set(null, list);
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM