Search code examples
javagenericstype-erasuremethod-signature

Wildcard types, type erasure and runtime signature: what happens on <T extends A & B> where A and B inherit a common ancestor?


(edit: fixed after comments)

Let us take a class or interface A and an interface B where both inherit a common ancestor X (assuming X is not Object). Let us have a method whose signature is:

<T extends A & B> void foo(final T arg)

What is the signature of foo at runtime? Is that void foo(X) or void foo(Object), and the JVM casts to X at runtime?


Solution

  • The erasure of a type parameter is always the erasure of its left-most bound, doesn't matter what other classes are up there in the inheritance hierarchy (JLS §4.6). So, the method is erased to:

    void foo(final A)
    

    Of course, as noted in comments, if A and B both are classes, that code will not compile. The type parameter bounds can not have multiple classes as bounds, but only a single class followed by any number of interfaces.

    See JLS §4.4 for the syntax of type variable declaration:

    TypeParameter:
        TypeVariable TypeBoundopt
    
    TypeBound:
        extends TypeVariable
        extends ClassOrInterfaceType AdditionalBoundListopt
    
    AdditionalBoundList:
        AdditionalBound AdditionalBoundList
        AdditionalBound
    
    AdditionalBound:
        & InterfaceType
    

    Any AdditionalBound should always be an InterfaceType.

    the JVM casts to X at runtime?

    Yes the compiler will add appropriate cast so that the code works as intended.