IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 系统运维 -> 为何需要使用泛型的通配符? --《JAVA编程思想》 56 -> 正文阅读

[系统运维]为何需要使用泛型的通配符? --《JAVA编程思想》 56

我们先来看一个导出类型的数组赋予基类型数组的例子:

public class Fruit {}
public class Apple extends Fruit {}
public class RedApple extends Apple {}
public class CovariantArrays {

    public static void main(String[] args) {
        Fruit[] fruits = new Apple[10];
        fruits[0] = new Apple();
        System.out.println("成功存入 Apple");
        fruits[1] = new RedApple();
        System.out.println("成功存入 RedApple");
        fruits[2] = new Fruit();
        System.out.println("成功存入 Fruit");
    }

}
成功存入 Apple
成功存入 RedApple
Exception in thread "main" java.lang.ArrayStoreException: mtn.baymax.charpter15.Fruit
	at mtn.baymax.charpter15.CovariantArrays.main(CovariantArrays.java:16)

上述代码虽然能通过编译,但在运行时会抛出 ArrayStoreException 表示我们将错误的类型存储至数组中。

fruits 数组的实际引用仍然是 Apple 类型的数组,编译器虽然允许你将任何 Fruit 类型及其导出类放入数组中,但数组存储的元素类型是不可变的,只能存放 Apple 类型或者及其子类,故 fruits 中不能存储 Fruit 类型。

实际上,数组的向上转型在这是不合适的。但可怕的是,即使存储类型不对,也能通过编译,我们只能在运行期间发现这个错误。

但有时候我们希望一个存储 Fruit 类型的容器来接收各类存储 Fruit 及 Fruit 导出类的容器,这时该怎么办呢?

我们首先想到用 List 来作为容器,List 会对存入的元素做类型检查,加强代码的安全性。

不过持有 Apple 类型的 List 仍然不等于持有 Fruit 类型的 List 。这是因为 Fruit 类型的 List 可以存储 Fruit 及其任何导出类,但 Apple 类型的 List 只能存储 Apple 类型及其子类,这两种容器本质是不同的(想象一下,你能在 Apple 类型的 List 中放入 Orange 类型嘛?)。故下述代码是无法通过编译的。

public class GenericsAndCovariance {

    public void printFruit(ArrayList<Fruit> fruits) {
        for (Fruit fruit : fruits) {
            System.out.println(fruit);
        }
    }

    public static void main(String[] args) {
        ArrayList<Apple> apples = new ArrayList<>();
        GenericsAndCovariance gc = new GenericsAndCovariance();
        //类型错误,无法编译
        //gc.printFruit(apples);
    }

}

想要 fruits 能接收持有任何 Fruit 导出类型的 List ,使用泛型的通配符便可以解决。

public class GenericsAndCovariance {

    public void printFruit(ArrayList<? extends Fruit> fruits) {
        for (Fruit fruit : fruits) {
            System.out.println(fruit);
        }
    }

    public static void main(String[] args) {
        ArrayList<Apple> apples = new ArrayList<>();
        apples.add(new Apple());
        apples.add(new Apple());
        apples.add(new Apple());
        GenericsAndCovariance gc = new GenericsAndCovariance();
        gc.printFruit(apples);
        ArrayList<Fruit> fruits = new ArrayList<>();
        fruits.add(new Fruit());
        fruits.add(new Fruit());
        fruits.add(new Fruit());
        gc.printFruit(fruits);
    }

}

mtn.baymax.charpter15.Apple@1b6d3586
mtn.baymax.charpter15.Apple@4554617c
mtn.baymax.charpter15.Apple@74a14482
mtn.baymax.charpter15.Fruit@1540e19d
mtn.baymax.charpter15.Fruit@677327b6
mtn.baymax.charpter15.Fruit@14ae5a5

ArrayList<? extends Fruit> fruits 表示持有任何继承自 Fruit 类型的 List,故 fruits 可以接收持有 Frult 和 Apple 类型的 List。

虽然我们可以正常读取 fruits 中存储的元素,但我们不能往 fruits 中存放任何元素,哪怕 Object 也不行,这又是为什么呢?

    public void printFruit(ArrayList<? extends Fruit> fruits) {
        for (Fruit fruit : fruits) {
            System.out.println(fruit);
        }
        //下面三种类型均无法通过编译
        //fruits.add(new Fruit());
        //fruits.add(new Apple());
        //fruits.add(new Object());
    }

当任何持有 Fruit 导出类的 List 被赋值给 fruits 时,都会执行向上转型(如同第一个例子中数组向上转型),不过这里向上转型的类型并不是某个具体类型,我们只知道它继承自 Fruit,可能是 Fruit 、Apple,还有可能是 Orange、Banana 。在无法确定 List 容器中具体类型的情况下,编译器禁止我们往容器中添加任何数据,但因知道存储的类型都继承自 Fruit,故在读取的时候,可以安全的向上转型为 Fruit。

本次分享至此结束,希望本文对你有所帮助,若能点亮下方的点赞按钮,在下感激不尽,谢谢您的【精神支持】。

若有任何疑问,也欢迎与我交流,若存在不足之处,也欢迎各位指正!

  系统运维 最新文章
配置小型公司网络WLAN基本业务(AC通过三层
如何在交付运维过程中建立风险底线意识,提
快速传输大文件,怎么通过网络传大文件给对
从游戏服务端角度分析移动同步(状态同步)
MySQL使用MyCat实现分库分表
如何用DWDM射频光纤技术实现200公里外的站点
国内顺畅下载k8s.gcr.io的镜像
自动化测试appium
ctfshow ssrf
Linux操作系统学习之实用指令(Centos7/8均
上一篇文章      下一篇文章      查看所有文章
加:2021-09-27 14:29:21  更:2021-09-27 14:30:18 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/15 15:53:15-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码