600字范文,内容丰富有趣,生活中的好帮手!
600字范文 > 【Java 泛型】泛型用法 ( 泛型编译期擦除 | 上界通配符 <? extends T> |

【Java 泛型】泛型用法 ( 泛型编译期擦除 | 上界通配符 <? extends T> |

时间:2024-08-09 12:53:03

相关推荐

【Java 泛型】泛型用法 ( 泛型编译期擦除 | 上界通配符 <? extends T> |

文章目录

一、泛型擦除二、泛型的上界通配符 <? extends T>三、泛型的下界通配符 <? super T>

一、泛型擦除

泛型只保留到 编译期 , 在 编译完毕后 , 泛型就不存在了 ;

在运行时 , 通过反射 , 调用泛型类 , 即使违反了泛型规则 , 也能进行相关操作 , 这是因为 在运行时 , 已经没有泛型相关的限制 , 泛型限制在编译时就已经被擦除了 ;

但是 泛型的信息 , 保存在了常量表中 , 仍然可以获取到 ;

泛型擦除 是为了 泛型可以兼容 老版本的 JDK 而设计的 ,

泛型是 JDK 5 加入的 , 如果添加了泛型 , 导致字节码的格式改变 , 必然导致之前版本的 JDK 无法运行有泛型的字节码程序 ;

给定一个 Demo.java 类 , 其中定义了一个<T> T get()方法 ;

public class Demo {public <T> T get(){T t = null;return t;}}

将其编译后 , 查看字节码附加信息 ;

D:\java>javap -v Demo.classClassfile /D:/java/Demo.classLast modified -9-7; size 307 bytesMD5 checksum 727bc59421b23a5f0a31af0e91630ab8Compiled from "Demo.java"public class Demominor version: 0major version: 52flags: ACC_PUBLIC, ACC_SUPERConstant pool:#1 = Methodref#3.#14 // java/lang/Object."<init>":()V#2 = Class #15 // Demo#3 = Class #16 // java/lang/Object#4 = Utf8<init>#5 = Utf8()V#6 = Utf8Code#7 = Utf8LineNumberTable#8 = Utf8get#9 = Utf8()Ljava/lang/Object;#10 = Utf8Signature#11 = Utf8<T:Ljava/lang/Object;>()TT;#12 = Utf8SourceFile#13 = Utf8Demo.java#14 = NameAndType #4:#5// "<init>":()V#15 = Utf8Demo#16 = Utf8java/lang/Object{public Demo();descriptor: ()Vflags: ACC_PUBLICCode:stack=1, locals=1, args_size=10: aload_01: invokespecial #1 // Method java/lang/Object."<init>":()V4: returnLineNumberTable:line 1: 0public <T extends java.lang.Object> T get();descriptor: ()Ljava/lang/Object;flags: ACC_PUBLICCode:stack=1, locals=2, args_size=10: aconst_null1: astore_12: aload_13: areturnLineNumberTable:line 3: 0line 4: 2Signature: #11// <T:Ljava/lang/Object;>()TT;}SourceFile: "Demo.java"

Demo 中的 get 方法类型返回值是 Ljava/lang/Object , 不是泛型 T , 这就是泛型在字节码中被擦除了 ;

descriptor: ()Ljava/lang/Object;

执行下面的代码 , 在运行时 , 使用反射 , 向 list1 集合中添加 int 类型的元素 , 添加成功 ; 说明在运行时 , 不再进行泛型检查 , 即使不符合泛型要求 , 也能操作成功 ;

import java.lang.reflect.InvocationTargetException;import java.lang.reflect.Method;import java.util.ArrayList;import java.util.List;public class Main {public static void main(String[] args) {// 编译器 在 编译期 进行检查List<String> list1 = new ArrayList<>();//list1.add(1);// 编译器 在 编译期 不进行检查List list2 = new ArrayList<String>();//list2.add(1);try {Method method = ArrayList.class.getMethod("add", Object.class);method.invoke(list1, 1);System.out.println("list1 集合大小 : " + list1.size());} catch (NoSuchMethodException e) {e.printStackTrace();} catch (InvocationTargetException e) {e.printStackTrace();} catch (IllegalAccessException e) {e.printStackTrace();}}}

执行结果 :

二、泛型的上界通配符 <? extends T>

泛型 上界通配符 :<T extends Person>表示泛型 T 是 Person 的子类 ,<? extends T>泛型类型 只能是 T 的子类 ;

<T extends Person>只能在声明泛型时使用 , 不能在 使用 泛型 时使用 ;

public class Data<T extends Person> {}

<? extends T>只能在使用 泛型 时使用 , 不能在声明 泛型类/方法 时 使用 ;

Data<? extends Person> data6 = new Data<>();

333 个有继承关系的类 :

public class Animal {}

public class Person extends Animal {}

public class Woman extends Person {}

泛型类 :该泛型类接收一个泛型 , 该泛型 T 是 Person 的子类 ;

public class Data<T extends Person> {}

main 函数 :

// 上边界通配符// 符合要求 , 可设置 Woman 的父类 , Woman 以及 Person 类Data<? super Woman> data4 = new Data<>();// 符合要求 , 可设置 Person 类Data<? super Person> data5 = new Data<>();// 不符合要求 , Animal 是最顶层的类 , 其取值都不符合 <T extends Person> 要求Data<? super Animal> data6 = new Data<>();

报错信息 :传入不符合要求的泛型的报错信息 ;

三、泛型的下界通配符 <? super T>

泛型 下界通配符 :<? super T>泛型类型 只能是 T 的父类 ;

<? super T>只能在使用 泛型 时使用 , 不能在声明 泛型类/方法 时 使用 ;

Data<? super Person> data6 = new Data<>();

333 个有继承关系的类 :

public class Animal {}

public class Person extends Animal {}

public class Woman extends Person {}

泛型类 :该泛型类接收一个泛型 , 该泛型 T 是 Person 的子类 ;

public class Data<T extends Person> {}

main 函数 :

// 上边界通配符// 符合要求 , 可设置 Woman 的父类 , Woman 以及 Person 类Data<? super Woman> data4 = new Data<>();// 符合要求 , 可设置 Person 类Data<? super Person> data5 = new Data<>();// 不符合要求 , Animal 是最顶层的类 , 其取值都不符合 <T extends Person> 要求//Data<? super Animal> data6 = new Data<>();

报错信息 :不符合要求 , Animal 是最顶层的类 , 其取值都不符合 要求

【Java 泛型】泛型用法 ( 泛型编译期擦除 | 上界通配符 <? extends T> | 下界通配符 <? super T> )

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。