了解泛型吗?
参考文章:blog.csdn.net/qq_43546676…
泛型就是在编译时检查类型安全,并且不需要强制进行类型转换
泛型擦除了解吗?
泛型擦除即在编译生成的字节码中,所有声明泛型的地方都会被擦除,擦除之后设置的类型会根据是否指定泛型上界而不同:
-
如果没有指定泛型上界,则所有的泛型类型在编译之后都替换为 Object 类型
即在
generic.set("张三")时,会将 String 类型的参数擦除为 Object 类型通过反编译指令
javap -c得到字节码,发现在 11 行 set 值类型为 Object,在 15 行 get 值类型为 Object,在 18 行编译器会插入checkcast语句将 Object 类型转为 String 类型public class GenericTest<T> { private T t; public T get(){ return t; } public void set(T t) { this.t = t; } public static void main(String[] args) { GenericTest<String> generic = new GenericTest<>(); generic.set("张三"); generic.get(); } } // 通过 javap -c 反编译得到字节码指令 public static void main(java.lang.String[]); Code: 0: new #3 // class com/example/nettystudy/AlgorithmTest/GenericTest 3: dup 4: invokespecial #4 // Method "<init>":()V 7: astore_1 8: aload_1 9: ldc #5 // String 张三 11: invokevirtual #6 // Method set:(Ljava/lang/Object;)V 14: aload_1 15: invokevirtual #7 // Method get:()Ljava/lang/Object; 18: checkcast #8 // class java/lang/String 21: astore_2 22: return
-
如果指定泛型上界,则所有的泛型类型在编译之后都替换为 String 类型(也就是上界的类型)
可以发现在字节码第 11 行和第 15 行即 set 和 get 时,类型都为 String 类型,而不是 Object 类型
public class GenericTest<T extends String> { private T t; public T get(){ return t; } public void set(T t) { this.t = t; } public static void main(String[] args) { GenericTest<String> generic = new GenericTest<>(); generic.set("张三"); String s = generic.get(); } } // 通过 javap -c 反编译得到字节码 public static void main(java.lang.String[]); Code: 0: new #3 // class com/example/nettystudy/AlgorithmTest/GenericTest 3: dup 4: invokespecial #4 // Method "<init>":()V 7: astore_1 8: aload_1 9: ldc #5 // String 张三 11: invokevirtual #6 // Method set:(Ljava/lang/String;)V 14: aload_1 15: invokevirtual #7 // Method get:()Ljava/lang/String; 18: astore_2 19: return