Generics (generic erasure, generics can be reflected, limitations and problems of generics)

1. Generic erasure

泛型的擦除是是用一种称为类型消除( type erasure)的方法来实现的。
当泛型存在于编译时,一旦被确认安全使用时,
就会将其转换为原生类型也就是擦除成原生类型。

泛型擦除是指泛型代码在编译后,都会被擦除为原生类型。例如
Zoo<Fish>和Zoo<Bird>,实际上在运行时都是同一种类型,即
原生类型Zoo。这就意味着运行时,Java并不存在类型参数这一概念,
因此将无法任何相关的参数类型信息。

例如下面的代码证实了泛型擦除:
package Generic.wildcardsAndBoundaries;

public class Test {
    
    
    public static void main(String[] args) {
    
    
        Zoo<Fish> fishZoo = new Zoo<>(new Fish());
        Zoo<Bird> birdZoo = new Zoo<>(new Bird());
        System.out.println("两者的类型相同吗? " + fishZoo.getClass().equals(birdZoo.getClass()));
    }
}

operation result:
Insert picture description here


1.1 Why erase generics

擦除是java泛型方法实现的一种折中办法。
因为擦除的核心动机是使得泛化的代码可以使用非泛化的类库,
反之亦然,为了让非泛型的代码和泛型的代码共存,实现擦除非常可靠!

1.2 How to erase

其实擦除的实质就是将原有的类型参数替换成即非泛化的上界。如:
public class Computer<E> {
    
    
    private E e;
    public Cmputer(E e){
    
    
        this.e=e;
    }
    public E apply(){
    
    
        return this.e;
    }
}
上方代码经过编译后,将被编译成以下代码形式:
public class Computer {
    
    
    private Object e;

    public Computer(Object e) {
    
    
        this.e = e;
    }

    public Object apply() {
    
    
        return e;
    }
}
通过比较你会发现原有类型参数消失了,取而代之为参数类型Object,
这是因为Computer<E>没有指明上界,编译器将其自动擦除成顶类Object类型

若指明了上界如<E extends electrical>,则会有如下翻译:

Insert picture description here


1.3 Multiple border erasure

Insert picture description here


2 Generics can reflect

Insert picture description here


3 Restrictions and problems of generics

因为擦除机制使得运行时丢失了泛型信息,
因此一些理所当然的功能在java泛型系统中得不到支持。
  • Restriction 1:
    In order to ensure type safety, you cannot use generic type parameters to create instances
    // illegal T object=new T();
  • Limitation 2:
    You cannot declare a generic instance array, which will cause a runtime error.
    // Illegal T[] numbers = new T[capcity];
    But you can circumvent this by creating an Object type array and converting its type to E[] limit.
    T[] number= (E[])new Object[capcity]:
  • Restriction 3:
    In a static environment, the parameter type is not allowed to be a generic type. (Because all instances of a generic class have the same runtime class, the static variables and methods of a generic class are shared by all its instances. Since they are shared, you don’t need to redefine the same generic Type, if you don’t define the same generic type, and you cannot achieve sharing (or consistency), there is no need to let this situation pass. Therefore, in a static environment, the parameter of the class is set to the generic type. Unlawful.)
  • Limitation 4:
    Generic class objects cannot be thrown or captured, because generic classes cannot inherit or implement the Throwable interface and its subclasses.

Guess you like

Origin blog.csdn.net/I_r_o_n_M_a_n/article/details/115203473