泛型(2)

泛型(2)

1、 泛型在继承上的体现

如果B是A的一个子类型(子类或者子接口),而G是具有泛型声明的类或接口,G并不是G的子类型!

比如:String是Object的子类,但是List并不是List的子类。

class A <T> extends superA<String>{......}

只有泛型类相同时,父类与子类之间才能体现继承关系。

例如:父类SuperA<String>与子类A<String>之间存在继承关系,类A的实例对象可以被SuperA引用体现多态性;但SuperB<Object>与B<String>之间没有继承关系。

2、 通配符的使用

当我们声明一个变量/形参时,这个变量/形参的类型是一个泛型类或泛型接口,例如:Comparator类型,但是我们仍然无法确定这个泛型类或泛型接口的类型变量的具体类型,此时我们考虑使用类型通配符 ? 。

1 通配符的理解

使用类型通配符:?

比如:List<?>Map<?,?>

List<?>List<String>List<Object> 等各种泛型List的父类。

2 通配符的读与写

写操作:

将任意元素加入到其中不是类型安全的:

Collection<?> c = new ArrayList<String>();

c.add(new Object()); // 编译时错误

因为我们不知道c的元素类型,我们不能向其中添加对象。add方法有类型参数E作为集合的元素类型。我们传给add的任何参数都必须是一个未知类型的子类。因为我们不知道那是什么类型,所以我们无法传任何东西进去。

唯一可以插入的元素是null,因为它是所有引用类型的默认值。

读操作:

另一方面,读取List<?>的对象list中的元素时,永远是安全的,因为不管 list 的真实类型是什么,它包含的都是Object。

java 复制代码
@Test
public void test1(){
    List<?>list = null;//通配符'?'不确定类型
    List<String> list1 =Arrays.asList(new String[]{"Qum","Dit","TuSu"});
    list = list1;
    Object obj = list.get(0);//get得到Object的接收值
    System.out.println(obj);//可以读取,不能写入
}

总结:使用通配符的集合,可读不可写。其他泛型类型的集合可以赋值给使用通配符的集合。

java 复制代码
@Test
public void test4(){
    List<?>list = new ArrayList<>();
    List <String> list1 = null;
    List <Integer>list2 = null;
    
    list = list1;//使用通配符作为泛型类型可以传入任意泛型类型的集合元素。
    list = list2;
    //list1 = list2;编译时错误,泛型类型不同不能传入集合元素。
}

3 使用注意点

注意点1:编译错误:不能用在泛型方法声明 ,返回值类型前面<>不能使用?

public static <?> void test(ArrayList<?> list){
}

注意点2:编译错误:不能用在泛型类的声明

class GenericTypeClass<?>{
}

注意点3:编译错误:不能用在创建对象上,右边属于创建集合对象

ArrayList<?> list2 = new ArrayList<?>();

4 有限制的通配符

  • <?>
    • 允许所有泛型的引用调用
  • 通配符指定上限:<? extends 类/接口 >
    • 使用时指定的类型必须是继承某个类,或者实现某个接口,即<=
java 复制代码
@Test
public void test2(){
    List<? extends Person> list = null;
    List<Object> list1 = null;
    List<Object> list2 = null;
    List<Person> list3 = null;
    List<Student> list4 = null;

    //list = list2;
    list = list3;//extend,继承于。 Person、Person的子类可以传入
    list = list4;
}
  • 无法写入数据,除了null
  • 通配符指定下限:<? super 类/接口 >
    • 使用时指定的类型必须是操作的类或接口,或者是操作的类的父类或接口的父接口,即>=
java 复制代码
@Test
public void test3(){
    List<? super Person> list = null;
    List<Object> list1 = null;
    List<Object> list2 = null;
    List<Person> list3 = null;
    List<Student> list4 = null;

    list = list2;
    list = list3;//super,写入父类, Person或者其父类可以传入
    //list = list4;
}
  • 可以写入Person及其子类的数据。
  • 说明:
  1. extends Number> //(无穷小 , Number]
    //只允许泛型为Number及Number子类的引用调用

    <? super Number> //[Number , 无穷大)
    //只允许泛型为Number及Number父类的引用调用

    <? extends Comparable>
    //只允许泛型为实现Comparable接口的实现类的引用调用

相关推荐
24k小善29 分钟前
Flink TaskManager详解
java·大数据·flink·云计算
想不明白的过度思考者35 分钟前
Java从入门到“放弃”(精通)之旅——JavaSE终篇(异常)
java·开发语言
.生产的驴1 小时前
SpringBoot 封装统一API返回格式对象 标准化开发 请求封装 统一格式处理
java·数据库·spring boot·后端·spring·eclipse·maven
猿周LV1 小时前
JMeter 安装及使用 [软件测试工具]
java·测试工具·jmeter·单元测试·压力测试
晨集1 小时前
Uni-App 多端电子合同开源项目介绍
java·spring boot·uni-app·电子合同
时间之城1 小时前
笔记:记一次使用EasyExcel重写convertToExcelData方法无法读取@ExcelDictFormat注解的问题(已解决)
java·spring boot·笔记·spring·excel
椰羊~王小美1 小时前
LeetCode -- Flora -- edit 2025-04-25
java·开发语言
凯酱1 小时前
MyBatis-Plus分页插件的使用
java·tomcat·mybatis
程序员总部2 小时前
如何在IDEA中高效使用Test注解进行单元测试?
java·单元测试·intellij-idea
oioihoii2 小时前
C++23中if consteval / if not consteval (P1938R3) 详解
java·数据库·c++23