栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

泛型、通配符以及PECS法则

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

泛型、通配符以及PECS法则

最近在阅读JDK源码的时候,经常在各种类、接口或者方法上看到各种复杂的泛型写法,不能很好地理解参数这样设计的好处或者意图是什么,因此在阅读相关博客资料后做如下总结归纳。

泛型
  • JDK5引入的新特性,提供了编译时类型安全检测机制。
  • 本质是参数化类型。
  • 好处是在编译时能够检查类型安全,并且所有的强制转换都是自动和隐式的。
受限泛型

有时候我们希望像使用普通类型那样使用泛型类型。

  • 向上转型一个泛型对象的引用
  • 向下转型一个泛型对象的引用

首先要说明的一点是,Java强制在创建对象的时候必须给类型参数制定具体的类型,不能使用通配符,比如new ArrayList()或者new ArrayList这种。

@Test
	public void test1() {
        //PE:Prodcer Extends
		ArrayList list = new ArrayList<>();
        
		//list.add(new Integer((1))); 编译错误
		Number number = list.get(0);
	}

只能读取,不能写入!

调用add()会导致编译失败,是因为我们在创建实例时,可能使用了E也可能使用了E的子类,编译器无法获取准确的信息,工作无法正常进行。而对于get()方法来说,由于我们是通过E或者E的子类来创建实例,而用超类来引用子类在Java中是合法的,所以我们能通过get()方法拿到一个E类型的引用。

@Test
	public void test2() {
		//CS:Consumer Super
		ArrayList list = new ArrayList<>();

		list.add(new Apple());
		//Apple apple = list.get(0);  编译错误
	}

只能写入,不能读取!

调用get()方法会导致编译失败,是因为我们在创建实例时,可能使用了E也可能使用了E的超类,当调用get()时编译器是无法知道准确信息的,而Java中超类引用子类的合法性又无法在这里得到应用(未知类的父类也是未知的)。而对于add()方法,虽然我们无法知道实例到底使用了E还是E的超类,但是我们可以确定加入E或者E的子类是没有问题的,因为超类引用子类在Java中是一个合法行为。

PECS法则

指"Producer Extends, Consumer Super",来自 Joshua Bloch的《Effective Java》。

换言之,生产者使用 ? extends,消费者使用 ?super。

  • 如果你想要从一个数据类型里获取数据,那么使用 ? extends 通配符。
  • 如果你想要把对象写入一个数据类型,那么使用 ? super 通配符。
  • 如果你既想存,又想取,那就别使用泛型通配符。
参考

Java泛型中<? extends E>和<? super E>的区别 --博客园

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/458816.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号