Detailed explanation of type erasure examples of Java generics

Time:2021-12-8

preface

The feature of Java generics was added from JDK 1.5. Therefore, in order to be compatible with previous versions, the implementation of Java generics adopts the strategy of “pseudo generics”, that is, Java supports generics in syntax, but the so-called “type erase” will be carried out in the compilation stage to replace all generic representations (contents in angle brackets) with specific types (its corresponding primitive type) is like there is no generics at all. Understanding type erasure is very helpful to make good use of generics, especially some seemingly “difficult and miscellaneous” problems. Understanding type erasure can be easily solved.

The type erasure principle of generics is:

• eliminate the type parameter declaration, that is, delete < > and its surrounding parts.

• infer and replace all type parameters with original ecological types according to the upper and lower bounds of type parameters: if the type parameters are unrestricted wildcards or there are no upper and lower bounds, replace them with object; if there are upper and lower bounds, take the leftmost qualified type (i.e. parent class) of type parameters according to the subclass replacement principle.

• to ensure type safety, insert cast code if necessary.

• automatically generate “bridge method” to ensure that the code after erasing the type still has generic “polymorphism”.

1 erase the type parameters in the class definition

1.1 unlimited type erasure

When there are no restrictions on the type parameters in the class definition, they are directly replaced with object in type erasure, such as < T > and <? > The type parameters of are replaced with object. See 1.

Figure 1: erasing type parameters in class definitions

1.2 restricted type erasure

When there are restrictions (upper and lower bounds) on the type parameters in the class definition, replace them with the upper or lower bounds of the type parameters in the type erasure, such as < T extensions number > and <? The type parameter of extensions number > is replaced with number, <? Super number > is replaced by object, see 2.

Figure 2: restricted type parameters in erase class definition

2 type parameters in erase method definition

The principle of type parameters in the definition of erasure method is the same as that in the definition of erasure class. Here, only the restricted type parameters in the definition of erasure method are taken as an example, see 3.

Figure 3: erasing type parameters in generic methods

3 bridging methods and polymorphism of generics

Consider the following code:


public interface Info&lt;T&gt; {
    // just return var:-) 
    T info(T var); 
}
public class BridgeMethodTest implements Info&lt;Integer&gt; {
    @Override
    public Integer info(Integer var) {
        return var;
    }
}

According to our previous experience, the code after erasing the type should look like this:


public interface Info {
    // just return var
    Object info(Object var);
}

public class BridgeMethodTest implements Info {
    @Override
    public Integer info(Integer var) {
        return var;
    }
}

However, it is obvious that the code after erasing the type is syntactically wrong: Although there is an info method in the bridgemethodtest class, it is inconsistent with the info method required to be overwritten by the info interface: the parameter type is inconsistent. In this case, the java compiler will automatically add a so-called “bridge method” to meet the requirements of Java syntax, and also ensure that polymorphism based on generics can be effective. Let’s decompile the bridgemethodtest.class file to see how the java compiler does it:


$ javap BridgeMethodTest.class 

Compiled from “BridgeMethodTest.java”

public class BridgeMethodTest implements Info<java.lang.Integer> {

public BridgeMethodTest();

public java.lang.Integer info(java.lang.Integer);

public java.lang.Object info(java.lang.Object);

}

It can be seen that the java compiler automatically adds two methods in bridgemethodtest: the default construction method and the info method with the parameter object. The info method with the parameter object is the “bridging method”. How to understand the word “bridge”? Let’s decompile bridgemethodtest to see:


// Decompiled by Jad v1.5.8e. Copyright 2001 Pavel Kouznetsov.                                                          
// Jad home page: http://www.geocities.com/kpdus/jad.html
// Decompiler options: packimports(3) 
// Source File Name:   BridgeMethodTest.java
 
 
public class BridgeMethodTest
    implements Info
{
 
    public BridgeMethodTest()
    {   
    }   
 
    public Integer info(Integer integer)
    {   
        return integer;
    }   
 
    public volatile Object info(Object obj)
    {   
        return info((Integer)obj);
    }   
}

The info (object) method builds a bridge between the parent class and the child class by calling the info (integer) method of the child class, that is, the info (object obj) method connects the parent class and the child class, so that the polymorphism of Java is still effective in the case of generics.

Of course, we don’t have to think too much about “bridging methods” when using generic polymorphism. The java compiler will take care of everything for us.

For more information on bridging methods, please refer to the relevant sections of JLS.

summary

This is the end of this article on Java generic type erasure. For more information about Java generic type erasure, please search previous articles of developeppaer or continue to browse the relevant articles below. I hope you will support developeppaer in the future!

reference material

•http://docs.oracle.com/javase/tutorial/java/generics/index.html

•http://docs.oracle.com/javase/tutorial/extra/generics/index.html