揭秘泛型本质一
![](https://img.haomeiwen.com/i5625017/2b2269ccbed6a31f.png)
由此可见运行时获取的类信息是一致的,泛型信息被擦除了,只保留了原始类型信息ArrayList
揭秘泛型本质二
工欲善其事必先利其器
- 在AS中引入ASM
ASM
下载完之后 通过本地文件导入
ASM.png
- 利用ASM查看译后的字节码文件
![](https://img.haomeiwen.com/i5625017/315c9cc48279a9e0.png)
- 查看文件AIPlate
package fastec.com.rrcc.generics.demo02;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
public class AIPlate<T extends Comparable<T>> implements Plate<T>{
private List<T> items = new ArrayList<T>(10);
public AIPlate(){
}
public void set(T t) {
items.add(t);
Collections.sort(items);
}
public T get(){
int index = items.size() -1;
if(index>= 0){
return items.get(index);
}else{
return null;
}
}
@Override
public boolean equals(Object obj) {
return super.equals(obj);
}
@Override
public String toString() {
return "Plate{" +
"items=" + items +
'}';
}
}
通过ASM查看其字节码文件
// class version 51.0 (51)
// access flags 0x21
// signature <T::Ljava/lang/Comparable<TT;>;>Ljava/lang/Object;Lfastec/com/rrcc/generics/demo02/Plate<TT;>;
// declaration: fastec/com/rrcc/generics/demo02/AIPlate<T extends java.lang.Comparable<T>> implements fastec.com.rrcc.generics.demo02.Plate<T>
public class fastec/com/rrcc/generics/demo02/AIPlate implements fastec/com/rrcc/generics/demo02/Plate {
// compiled from: AIPlate.java
// access flags 0x2
// signature Ljava/util/List<TT;>;
// declaration: items extends java.util.List<T>
private Ljava/util/List; items
// access flags 0x1
public <init>()V
L0
LINENUMBER 13 L0
ALOAD 0
INVOKESPECIAL java/lang/Object.<init> ()V
L1
LINENUMBER 11 L1
ALOAD 0
NEW java/util/ArrayList
DUP
BIPUSH 10
INVOKESPECIAL java/util/ArrayList.<init> (I)V
PUTFIELD fastec/com/rrcc/generics/demo02/AIPlate.items : Ljava/util/List;
L2
LINENUMBER 15 L2
RETURN
L3
LOCALVARIABLE this Lfastec/com/rrcc/generics/demo02/AIPlate; L0 L3 0
// signature Lfastec/com/rrcc/generics/demo02/AIPlate<TT;>;
// declaration: this extends fastec.com.rrcc.generics.demo02.AIPlate<T>
MAXSTACK = 4
MAXLOCALS = 1
// access flags 0x1
// signature (TT;)V
// declaration: void set(T)
public set(Ljava/lang/Comparable;)V
L0
LINENUMBER 18 L0
ALOAD 0
GETFIELD fastec/com/rrcc/generics/demo02/AIPlate.items : Ljava/util/List;
ALOAD 1
INVOKEINTERFACE java/util/List.add (Ljava/lang/Object;)Z (itf)
POP
L1
LINENUMBER 19 L1
ALOAD 0
GETFIELD fastec/com/rrcc/generics/demo02/AIPlate.items : Ljava/util/List;
INVOKESTATIC java/util/Collections.sort (Ljava/util/List;)V
L2
LINENUMBER 20 L2
RETURN
L3
LOCALVARIABLE this Lfastec/com/rrcc/generics/demo02/AIPlate; L0 L3 0
// signature Lfastec/com/rrcc/generics/demo02/AIPlate<TT;>;
// declaration: this extends fastec.com.rrcc.generics.demo02.AIPlate<T>
LOCALVARIABLE t Ljava/lang/Comparable; L0 L3 1
// signature TT;
// declaration: t extends T
MAXSTACK = 2
MAXLOCALS = 2
// access flags 0x1
// signature ()TT;
// declaration: T get()
public get()Ljava/lang/Comparable;
L0
LINENUMBER 23 L0
ALOAD 0
GETFIELD fastec/com/rrcc/generics/demo02/AIPlate.items : Ljava/util/List;
INVOKEINTERFACE java/util/List.size ()I (itf)
ICONST_1
ISUB
ISTORE 1
L1
LINENUMBER 24 L1
ILOAD 1
IFLT L2
L3
LINENUMBER 25 L3
ALOAD 0
GETFIELD fastec/com/rrcc/generics/demo02/AIPlate.items : Ljava/util/List;
ILOAD 1
INVOKEINTERFACE java/util/List.get (I)Ljava/lang/Object; (itf)
CHECKCAST java/lang/Comparable
ARETURN
L2
LINENUMBER 27 L2
FRAME APPEND [I]
ACONST_NULL
ARETURN
L4
LOCALVARIABLE this Lfastec/com/rrcc/generics/demo02/AIPlate; L0 L4 0
// signature Lfastec/com/rrcc/generics/demo02/AIPlate<TT;>;
// declaration: this extends fastec.com.rrcc.generics.demo02.AIPlate<T>
LOCALVARIABLE index I L1 L4 1
MAXSTACK = 2
MAXLOCALS = 2
// access flags 0x1
public equals(Ljava/lang/Object;)Z
L0
LINENUMBER 35 L0
ALOAD 0
ALOAD 1
INVOKESPECIAL java/lang/Object.equals (Ljava/lang/Object;)Z
IRETURN
L1
LOCALVARIABLE this Lfastec/com/rrcc/generics/demo02/AIPlate; L0 L1 0
// signature Lfastec/com/rrcc/generics/demo02/AIPlate<TT;>;
// declaration: this extends fastec.com.rrcc.generics.demo02.AIPlate<T>
LOCALVARIABLE obj Ljava/lang/Object; L0 L1 1
MAXSTACK = 2
MAXLOCALS = 2
// access flags 0x1
public toString()Ljava/lang/String;
L0
LINENUMBER 40 L0
NEW java/lang/StringBuilder
DUP
INVOKESPECIAL java/lang/StringBuilder.<init> ()V
LDC "Plate{items="
INVOKEVIRTUAL java/lang/StringBuilder.append (Ljava/lang/String;)Ljava/lang/StringBuilder;
ALOAD 0
GETFIELD fastec/com/rrcc/generics/demo02/AIPlate.items : Ljava/util/List;
INVOKEVIRTUAL java/lang/StringBuilder.append (Ljava/lang/Object;)Ljava/lang/StringBuilder;
BIPUSH 125
INVOKEVIRTUAL java/lang/StringBuilder.append (C)Ljava/lang/StringBuilder;
INVOKEVIRTUAL java/lang/StringBuilder.toString ()Ljava/lang/String;
ARETURN
L1
LOCALVARIABLE this Lfastec/com/rrcc/generics/demo02/AIPlate; L0 L1 0
// signature Lfastec/com/rrcc/generics/demo02/AIPlate<TT;>;
// declaration: this extends fastec.com.rrcc.generics.demo02.AIPlate<T>
MAXSTACK = 2
MAXLOCALS = 1
// access flags 0x1041
public synthetic bridge get()Ljava/lang/Object;
L0
LINENUMBER 9 L0
ALOAD 0
INVOKEVIRTUAL fastec/com/rrcc/generics/demo02/AIPlate.get ()Ljava/lang/Comparable;
ARETURN
L1
LOCALVARIABLE this Lfastec/com/rrcc/generics/demo02/AIPlate; L0 L1 0
// signature Lfastec/com/rrcc/generics/demo02/AIPlate<TT;>;
// declaration: this extends fastec.com.rrcc.generics.demo02.AIPlate<T>
MAXSTACK = 1
MAXLOCALS = 1
// access flags 0x1041
public synthetic bridge set(Ljava/lang/Object;)V
L0
LINENUMBER 9 L0
ALOAD 0
ALOAD 1
CHECKCAST java/lang/Comparable
INVOKEVIRTUAL fastec/com/rrcc/generics/demo02/AIPlate.set (Ljava/lang/Comparable;)V
RETURN
L1
LOCALVARIABLE this Lfastec/com/rrcc/generics/demo02/AIPlate; L0 L1 0
// signature Lfastec/com/rrcc/generics/demo02/AIPlate<TT;>;
// declaration: this extends fastec.com.rrcc.generics.demo02.AIPlate<T>
MAXSTACK = 2
MAXLOCALS = 2
}
![](https://img.haomeiwen.com/i5625017/bb83e919d589fbe9.png)
父类Plate擦除之后变为,这个时候子类无法覆盖父类的方法
public abstract interface fastec/com/rrcc/generics/demo02/Plate {
// compiled from: Plate.java
// access flags 0x401
// signature (TT;)V
// declaration: void set(T)
public abstract set(Ljava/lang/Object;)V
// access flags 0x401
// signature ()TT;
// declaration: T get()
public abstract get()Ljava/lang/Object;
}
类型擦除与多态发生了冲突,要解决这个问题,就需要在AIPlate中生成一个桥方法
三 泛型擦除的残留
![](https://img.haomeiwen.com/i5625017/664ac025700b741b.png)
查看类文件 其签名信息保留其定义的格式,这样对分析字节码文件也是有益的
泛型类独有的标记,普通类是 没有的,JDK 5 之后才加入,标记了定义时的c成员签名(泛型参数列表、参数类型、返回值等)
网友评论