一篇文章带你了解Java泛型的super和extends

目录
  • 概念简单理解
  • 代码样例解读
  • 关于List<? super T>
    • add方面
    • 返回值方面
  • 关于List<? extendsT>
    • add方面
      • 返回值方面
  • 总结

概念简单理解

  • List<? extends T>表示该集合中存在的都是类型T的子类,包括T自己
  • List<? super T>表示该集合中存的都是类型T的父类,包括T自己

代码样例解读

父子类代码:

/**
 * 生物
 */
static class Biological{
}
/**
 * 动物
 */
static class Animal extends Biological{
}
/**
 * 植物
 */
static class Plant extends Biological{
}

static class Dog extends Animal{
}
static class Cat extends Animal{
}
static class Flower extends Plant{
}
static class Tree extends Plant{
}

关系图:

测试代码:

public static void main(String[] args) {
    List<? super Animal> listA = new ArrayList<>();
    List<? extends Plant> listB = new ArrayList<>();
    //listA.add(new Biological());
    listA.add(new Animal());
    listA.add(new Dog());
    //listA.add(new Flower());
    Object object = listA.get(0);
    //listB.add(new Plant());
    //listB.add(new Flower());
    listB.add(null);
    Plant plant = listB.get(0);
}

关于List<? super T>

add方面

List<? super Animal> listA = new ArrayList<>();
listA.add(new Biological());

执行上面这行代码是不允许的,因为listA的集合类型是Animal或者更高的父类,想一下如果代表的类型是Animal,那怎么允许add它的父类Biological呢?当然不允许了。

listA.add(new Animal());
listA.add(new Dog());

执行上面这两句就是可以正常执行的,因为无论是Animal还是Animal的子类Dog,都是可以存到集合类型是Animal或者更高的父类的集合中的。有点拗口,不过就是这个意思。

listA.add(new Flower());

添加Flower当然是不可以的,因为它不是Animal的子类。

返回值方面

Object object = listA.get(0);

因为listA的集合类型是Animal或者更高的父类,所以不清楚到底会是哪个类,但是我们都应该清楚所有类的父类都是Object,所以返回值是Object类型的。

关于List<? extendsT>

add方面

List<? extends Plant> listB = new ArrayList<>();
listB.add(new Plant());

执行上面的代码是不允许的,因为listB的集合类型是Plant或Plant的子类,想一下如果代表的类型是Plant的子类Tree,那么怎么可能可以add它的父类Plant呢?所以跟上面的那个理解差不多,就是反过来理解。看图可以更加清晰。

listB.add(new Flower());

这个同理,如何代表的类型是Flower的子类Rose(玫瑰花),这样当然不可以add它的父类Flower了。

listB.add(null);

特殊情况就是这个,可以add null,但是也没意义啊。

返回值方面

Plant plant = listB.get(0);

因为listB的集合类型是Plant或者它的子类,所以不清楚到底会是哪个类,但是我们可以知道,最高的类型就是Plant了,所以返回值就是Plant类型的。

总结

  • List<? super T>表示该集合中存的都是类型T的父类,包括T自己

    • add:不能add任何对象(特例:可以添加null)
    • get:get返回的对象类型为T
  • List<? extends T>表示该集合中存在的都是类型T的子类,包括T自己
    • add:只能添加T及T的子类
    • get:get返回的对象类型为Object

本篇文章就到这里了,希望能给你带来帮助,也希望您能够多多关注我们的更多内容!

(0)

相关推荐

  • Java泛型extends关键字设置边界的实现

    本文主要介绍在泛型定义中的< >中的占位符如何配合extends关键字使用,形如<T extends Integer>.泛型定义存在于这三种形式中:泛型类.泛型接口.泛型方法. 一般的泛型定义中的<T>,相当于<T extends Object>,而类型擦除则会将类型参数擦除成T的上界,即Object.则在泛型定义中作为T类型的对象可以调用Object的函数和属性. 使用了extends的泛型定义中的<T extends Integer>,其上界

  • 详解怎么用Java的super关键字

    Java的super关键字 当子类重写父类的方法后,子类对象将无法直接访问父类被重写的方法.为了解决这个问题,在Java中专门提供了一个super关键字来访问父类的成员,例如访问父类的成员变量.成员方法和构造方法.下面分两种情况来学习一下super关键字的具体用法. (1)使用super关键字调用父类的成员变量和成员方法,具体格式如下: super.成员变量 super.成员方法([参数1,参数2...]) 接下来通过一个案例来学习如何使用super关键字调用父类的成员变量和成员方法,如文件1所

  • 一篇文章带你入门java泛型

    目录 一.什么是泛型 二.语法 三.示例 1.简单示例 2.返回最大值-支持各种数据类型 3.泛型类 4.类型通配符 总结 一.什么是泛型 Java 泛型(generics)是 JDK 5 中引入的一个新特性, 泛型提供了编译时类型安全检测机制,该机制允许程序员在编译时检测到非法的类型. 泛型的本质是参数化类型,也就是说所操作的数据类型被指定为一个参数. 二.语法 你可以写一个泛型方法,该方法在调用时可以接收不同类型的参数.根据传递给泛型方法的参数类型,编译器适当地处理每一个方法调用. 下面是定

  • Java泛型extends及super区别实例解析

    <? extends T>和<? super T>是Java泛型中的"通配符(Wildcards)"和"边界(Bounds)"的概念. <? extends T>:是指"上界通配符(Upper Bounds Wildcards)" <? super T>:是指"下界通配符(Lower Bounds Wildcards)" 为什么要用通配符和边界? 使用泛型的过程中,经常出现一种很

  • Java泛型的类型擦除示例详解

    目录 前言 泛型的类型擦除原则是: 1 擦除类定义中的类型参数 1.1 无限制类型擦除 1.2 有限制类型擦除 2 擦除方法定义中的类型参数 3 桥接方法和泛型的多态 总结 参考资料 前言 Java泛型这个特性是从JDK 1.5才开始加入的,因此为了兼容之前的版本,Java泛型的实现采取了"伪泛型"的策略,即Java在语法上支持泛型,但是在编译阶段会进行所谓的"类型擦除"(Type Erasure),将所有的泛型表示(尖括号中的内容)都替换为具体的类型(其对应的原生

  • 一篇文章带你了解Java泛型的super和extends

    目录 概念简单理解 代码样例解读 关于List<? super T> add方面 返回值方面 关于List<? extendsT> add方面 返回值方面 总结 概念简单理解 List<? extends T>表示该集合中存在的都是类型T的子类,包括T自己 List<? super T>表示该集合中存的都是类型T的父类,包括T自己 代码样例解读 父子类代码: /** * 生物 */ static class Biological{ } /** * 动物 */

  • 一篇文章带你了解java泛型--泛型类,泛型方法,泛型接口

    目录 Java 泛型 Java 泛型是什么 泛型类 泛型类的格式 泛型类举例 泛型方法 泛型方法的格式 泛型方法举例 泛型接口 泛型接口的格式 泛型接口举例 泛型接口实现类: 测试接口类: 打印结果: 总结 Java 泛型 Java 泛型是什么 官方定义: 泛型是Java SE 1.5的新特性,泛型的本质就是参数化类型,也就是说所操作的数据类型被指定为一个参数 这种参数类型可以用在类.接口和方法的创建中,分别成为泛型类.泛型接口.泛型方法 优缺点: ​ 优点:可以不用再类型转换了 ​ 缺点:降低

  • 一篇文章带你了解Java Spring基础与IOC

    目录 About Spring About IOC Hello Spring Hello.java Beans.xml Test.java IOC创建对象的几种方式 Spring import settings Dependency Injection 1.构造器注入 2.set注入 3.拓展注入 P-namespcae&C-namespace Bean scopes singleton prototype Bean的自动装配 byName autowire byType autowire 小结

  • 一篇文章带你了解Java中ThreadPool线程池

    目录 ThreadPool 线程池的优势 线程池的特点 1 线程池的方法 (1) newFixedThreadPool (2) newSingleThreadExecutor (3) newScheduledThreadPool (4) newCachedThreadPool 2 线程池底层原理 3 线程池策略及分析 拒绝策略 如何设置maximumPoolSize大小 ThreadPool 线程池的优势 线程池做的工作主要是控制运行的线程数量,处理过程中将任务放入队列,然后在线程创建后启动这些

  • 一篇文章带你了解JAVA面对对象应用

    目录 常用API String类 关于String为啥不可改变 StringBuilder类 String.StringBuffer 和 StringBuilder 的区别: ArrayList 1.1ArrayList类概述 1.2ArrayList类常用方法 学生管理系统 总结 常用API API理解 什么是API API (Application Programming Interface) :应用程序编程接口 java中的API 指的就是 JDK 中提供的各种功能的 Java类,这些类将

  • 一篇文章带你了解Java容器,面板及四大布局管理器应用

    目录 什么是容器? 什么是面板? JPanel面板 JScrollPane面板 什么是布局管理器? 绝对布局管理器 流布局管理器 边界布局管理 网格布局管理器 容器.面板.布局管理器之间的关系 总结 什么是容器? 在Java的GUI界面设计中,关于容器的理解,从字面意思我们就可以认为它是存放控件的地方,而这个地方依托在窗体之上,常用的容器是container. 而关于container容器我们应该有这样的认识:Swing组件中的窗体通常是与容器相关联的,所以在一般情况下,建立完JFrame窗体后

  • 一篇文章带你入门java面向对象

    目录 一.继承 示例: 二.重载 三.接口 1.接口与类相似点: 2.接口与类的区别: 3.语法 四.枚举 1.定义 2.迭代枚举元素 3.在 switch 中使用枚举类 总结 一.继承 继承就是子类继承父类的特征和行为,使得子类对象(实例)具有父类的实例域和方法,或子类从父类继承方法,使得子类具有父类相同的行为 本章就以人.学生.老师作为例子.学生和老师都继承人这个对象,都有人的特征和行为,人就是父类,老师和学生就是子类 示例: 人类: package com.zhouzy.base.t7;

  • 一篇文章带你入门Java修饰符

    目录 定义 分类 访问控制修饰符 非访问控制修饰符 修饰符的使用说明 修饰类 修饰方法 访问控制修饰符 非访问控制修饰符 修饰变量 总结 定义 Java修饰符:修饰符用来定义类.方法或者变量,通常放在语句的最前端. 分类 主要分为2类: 访问控制修饰符 非访问控制修饰符 访问控制修饰符 可以使用访问控制符来保护对类.变量.方法和构造方法的访问.分为以下4中权限:private,default,protected,public. 权限说明: 修饰符 当前类 同包 子类(不同包) 不同包(其他类)

  • 一篇文章带你了解JAVA面对对象之继承与修饰符

    目录 Java面向对象之继承与修饰符 继承 1.含义 2.实现 3.好处 4.短处 5.成员变量的访问特点 7.继承中结构方法的访问特点 8.方法重写 9.java继承的注意事项 修饰符 1.package 2.import 3.权限修饰符 4.final 5.ianl修饰基本数据类型变量 6.final修饰引用数据类型变量 7.static 8.static访问的特点 总结 Java面向对象之继承与修饰符 继承 1.含义 继承是面向对象三大特征之一,能使子类具有父类的属性和方法,还可以在子类中

随机推荐