在这篇文章中用Jad说明了JDK1.5中的泛型是擦拭法实现,实际是通过编绎前处理,或者编译器实现的。但有人说Jad还不支持1.5的语法,那么从另一个角度证明一下,就有了这篇文章。
import
java.util.ArrayList;
public class Generic {
public static void main(String[] args) {
ArrayList list1 = new ArrayList();
list1.add( " 1 " );
String str1 = (String)list1.get( 0 );
ArrayList < String > list2 = new ArrayList < String > ();
list2.add( " 1 " );
String str2 = list2.get( 0 );
}
}
public class Generic {
public static void main(String[] args) {
ArrayList list1 = new ArrayList();
list1.add( " 1 " );
String str1 = (String)list1.get( 0 );
ArrayList < String > list2 = new ArrayList < String > ();
list2.add( " 1 " );
String str2 = list2.get( 0 );
}
}
取得上边这段代码的字节码:( 如何取得字节码见这里)
//
class version 49.0 (49)
// access flags 33
public class Generic {
// compiled from: Generic.java
// access flags 1
public <init>()V
L0 (0)
LINENUMBER 4 L0
ALOAD 0
INVOKESPECIAL java/lang/Object.<init>()V
RETURN
L1 (4)
LOCALVARIABLE this LGeneric; L0 L1 0
MAXSTACK = 1
MAXLOCALS = 1
// access flags 9
public static main([Ljava/lang/String;)V
L0 (0)
LINENUMBER 7 L0
NEW java/util/ArrayList
DUP
INVOKESPECIAL java/util/ArrayList.<init>()V
ASTORE 1
L1 (5)
LINENUMBER 8 L1
ALOAD 1
LDC "1"
INVOKEVIRTUAL java/util/ArrayList.add(Ljava/lang/Object;)Z
POP
L2 (10)
LINENUMBER 9 L2
ALOAD 1
ICONST_0
INVOKEVIRTUAL java/util/ArrayList.get(I)Ljava/lang/Object;
CHECKCAST java/lang/String
ASTORE 2
L3 (16)
LINENUMBER 11 L3
NEW java/util/ArrayList
DUP
INVOKESPECIAL java/util/ArrayList.<init>()V
ASTORE 3
L4 (21)
LINENUMBER 12 L4
ALOAD 3
LDC "1"
INVOKEVIRTUAL java/util/ArrayList.add(Ljava/lang/Object;)Z
POP
L5 (26)
LINENUMBER 13 L5
ALOAD 3
ICONST_0
INVOKEVIRTUAL java/util/ArrayList.get(I)Ljava/lang/Object;
CHECKCAST java/lang/String
ASTORE 4
L6 (32)
LINENUMBER 14 L6
RETURN
L7 (34)
LOCALVARIABLE args [Ljava/lang/String; L0 L7 0
LOCALVARIABLE list1 Ljava/util/ArrayList; L1 L7 1
LOCALVARIABLE str1 Ljava/lang/String; L3 L7 2
LOCALVARIABLE list2 Ljava/util/ArrayList; L4 L7 3
// signature Ljava/util/ArrayList<Ljava/lang/String;>;
// declaration: java.util.ArrayList<java.lang.String>
LOCALVARIABLE str2 Ljava/lang/String; L6 L7 4
MAXSTACK = 2
MAXLOCALS = 5
}
仔细看一下,每个代码块对应的都有
// access flags 33
public class Generic {
// compiled from: Generic.java
// access flags 1
public <init>()V
L0 (0)
LINENUMBER 4 L0
ALOAD 0
INVOKESPECIAL java/lang/Object.<init>()V
RETURN
L1 (4)
LOCALVARIABLE this LGeneric; L0 L1 0
MAXSTACK = 1
MAXLOCALS = 1
// access flags 9
public static main([Ljava/lang/String;)V
L0 (0)
LINENUMBER 7 L0
NEW java/util/ArrayList
DUP
INVOKESPECIAL java/util/ArrayList.<init>()V
ASTORE 1
L1 (5)
LINENUMBER 8 L1
ALOAD 1
LDC "1"
INVOKEVIRTUAL java/util/ArrayList.add(Ljava/lang/Object;)Z
POP
L2 (10)
LINENUMBER 9 L2
ALOAD 1
ICONST_0
INVOKEVIRTUAL java/util/ArrayList.get(I)Ljava/lang/Object;
CHECKCAST java/lang/String
ASTORE 2
L3 (16)
LINENUMBER 11 L3
NEW java/util/ArrayList
DUP
INVOKESPECIAL java/util/ArrayList.<init>()V
ASTORE 3
L4 (21)
LINENUMBER 12 L4
ALOAD 3
LDC "1"
INVOKEVIRTUAL java/util/ArrayList.add(Ljava/lang/Object;)Z
POP
L5 (26)
LINENUMBER 13 L5
ALOAD 3
ICONST_0
INVOKEVIRTUAL java/util/ArrayList.get(I)Ljava/lang/Object;
CHECKCAST java/lang/String
ASTORE 4
L6 (32)
LINENUMBER 14 L6
RETURN
L7 (34)
LOCALVARIABLE args [Ljava/lang/String; L0 L7 0
LOCALVARIABLE list1 Ljava/util/ArrayList; L1 L7 1
LOCALVARIABLE str1 Ljava/lang/String; L3 L7 2
LOCALVARIABLE list2 Ljava/util/ArrayList; L4 L7 3
// signature Ljava/util/ArrayList<Ljava/lang/String;>;
// declaration: java.util.ArrayList<java.lang.String>
LOCALVARIABLE str2 Ljava/lang/String; L6 L7 4
MAXSTACK = 2
MAXLOCALS = 5
}
INVOKEVIRTUAL java/util/ArrayList.get(I)Ljava/lang/Object;
CHECKCAST java/lang/String
有没有泛型的字节码是一样的,说明在运行时,都进行了转型,所以说上一篇文章的说明应改是正确的。