新的JEP Candidate旨在简化处理Java中复杂的类型变异的概念。这个新的JEP Candidate可能会在Java 10中推出,提供了在定义的泛型类型中指定目标对象默认变异的方法,而不是在泛型类型实例化时通过通配符指定。这个新方案并不会代替通配符,而是减少对通配符的需求。

\\

类型变异这个概念对于很多开发人员来说仍然比较模糊,在Java中通过不太普及的通配符来解决这个问题并没有很大帮助。因此,为了帮助我们的读者能够理解这款JEP的潜在影响力,在本文中我们将首先解释什么是类型变异,目前Java中是怎么解决它的,之后将介绍这个新方案能实现什么。

\\

变异、协变和逆变

\\

以下的代码属于传统的在线购物应用程序:

\\

public class Product {\/* ... */\}\\public class FrozenProduct extends Product {\    /* ... */\}\

\\

如果有个方法scan(Product product),我们调用它传递FrozenProduct对象,调用工作没有问题,这是众所周知的多态性的一般规则。但是当参数中包含泛型时,就不能使用相同的逻辑,以下的代码将无法编译:

\\

private void addAllProducts(List\u0026lt;Product\u0026gt; products) {\/* Check product stock */\shoppingCart.addAll(products);\}\\private void freezerSection() {\    List\u0026lt;FrozenProduct\u0026gt; frozenProducts = /* select frozen products */;\    addAllProducts(frozenProducts); // ERROR: List\u0026lt;Product\u0026gt; expected\                                    //        List\u0026lt;FrozenProduct\u0026gt; found\}\

\\

当在Java中使用泛型时,并没有关于目标类型和其子类型或超类型之间兼容性的假设。换句话说,当使用泛型时,我们默认目标类型是不变的,它只接受明确的类型。

\\

然而,在上面的例子中,我们可以看到addAllProducts方法可以处理List of Product或是其子类型。当泛型参数可以接受其目标类型或是它的任何子类型,我们就说这个类型是协变的,在Java中可以用extends表示:

\\

private void addAllProducts(List\u0026lt;? extends Product\u0026gt; products) {\/* Check product stock */\shoppingCart.addAll(products);\}\\private void freezerSection() {\    List\u0026lt;FrozenProduct\u0026gt; frozenProducts =  /* select frozen products */;\    addAllProducts(frozenProducts); // works with no problem\}\

\\

在这些例子中,接受的目标类型的变异是子类型。在一些其他例子中,目标类型的变异不是子类型,而是超类型。考虑以下的情况:

\\

private boolean askQuestion(Predicate\u0026lt;String\u0026gt; p) {\return p.test(\"hello\");\}\\private void applyPredicate() {\    Predicate\u0026lt;Object\u0026gt; evenLength = o -\u0026gt; o.toString().length() % 2 == 0;\    askQuestion(evenLength); // ERROR: Predicate\u0026lt;String\u0026gt; expected\                             //        Predicate\u0026lt;Object\u0026gt; found\}\

\\

在这种情况下,我们可以看到使用string “hello”到lambda o -\u0026gt; o.toString().length() % 2 == 0中不会发生问题,然而,编译器不允许我们这么做。askQuestion可以处理Predicate of String或其任意超类型:我们就说这种情况下的目标类型是逆变的,在Java中可以用super表示:

\\

private boolean askQuestion(Predicate\u0026lt;? super String\u0026gt; p) {\return p.test(\"hello\");\}\\private void applyPredicate() {\    Predicate\u0026lt;Object\u0026gt; evenLength = o -\u0026gt; o.toString().length() % 2 == 0;\    askQuestion(evenLength); // works with no problem\}\

\\

通配符是创建类型变异的一种非常灵活的方法,因为它允许你在不同地方对同种类型定义不同的变异。比如说,在上面的例子里我们定义addAllProducts是协变的参数,但在其他地方根据我们的需求,可以定义它为逆变或是不变的。然而缺点是必须在每个地方根据需要明确指定变异,这样会造成很多的冗余和混乱。所以新的方案应运而生。

\\

在声明时指定默认变异

\\

通配符的最主要的问题是它们比开发人员通常需要的还要灵活。在Predicate\u0026lt;String\u0026gt;的例子中,我们理论上可以创建一个方法Predicate\u0026lt;? extends String\u0026gt;,然而,可以用到的用例有限(可能根本没有)。在大量情况下,只有一个类型变异有意义,为了反映出这一点,JEP 300提供了在声明泛型类型时指定默认变异的方法,而不是在实例化时指定默认变异。比如说,用了这种方案,可以使用逆变的关键字Predicate\u0026lt;contravariant T\u0026gt;来重写接口Predicate\u0026lt;T\u0026gt;,这就代表着任何时候开发人员写Predicate\u0026lt;String\u0026gt;都会被隐含地理解为Predicate\u0026lt;? super String\u0026gt;

\\

这个新功能的语法尚未决定,但是已经有了一些备选项:使用新的显式关键字,如Function\u0026lt;contravariant T, covariant R\u0026gt;,或遵循其他语言的先例,如Scala中的符号(Function\u0026lt;-T, +R\u0026gt;),或是C#中的较短关键字(Function\u0026lt;in T, out R\u0026gt;)。在解决语法问题之前,还需要解决一些重要的技术问题,即默认变异和通配符之间的交互,默认变异对现有代码产生的影响,以及变异类型兼容性检查的实际机制。

\\

最后值得提出的一点是,JEP 300仅会处理新的默认变异,但不会修改Java库中可用的任何类和接口。如果之后JEP 300再发展可能会考虑处理这种情况,但也只是在其他版本的JEP中执行。

\\

查看英文原文:New JEP Would Simplify Java Type Variance

新JEP将简化Java类型变异相关推荐

  1. Effective Java之请不要在新代码中使用原生态类型(二十三)

    1.泛型与原生态类型的概念 泛型就是带一个或多个类型参数E的类或者接口,而原生态类型是不带任何实际类型的泛型,例如List是原生态类型,List < String >或者List< ...

  2. Java类型推断将不再支持可变性规范

    Java类型推断是一项推荐的Java特性,允许开发人员使用var关键字代替显式的变量类型声明.最近的报道显示,由于社区内无法就区分可变和不可变变量的实现方式达成一致意见,Java类型推断将不再支持使用 ...

  3. 20155317 王新玮 2016-2017-2 《Java程序设计》第5周学习总结

    20155317 王新玮 2016-2017-2 <Java程序设计>第5周学习总结 教材学习内容总结 异常处理 & Collection与Map 异常继承架构 错误的对象继承ja ...

  4. java xtend_简化Java语法 Eclipse推出Xtend

    Java 程序员在使用 Ruby 编程时会有一种解放的感觉,一种从 Java 那繁琐的语法环境进入一个无拘无束.自由国度的感觉.随着 Clojure 和 Scala 等新语言的出现,这种对比的感觉会越 ...

  5. 用Groovy思考 第一章 用Groovy简化Java代码

    用Groovy思考  第一章 用Groovy简化Java代码 作者:chszs,转载需注明.博客主页:http://blog.csdn.net/chszs 1. Groovy的安装 目前Groovy的 ...

  6. 深入理解Java类型信息(Class对象)与反射机制

    关联文章: 深入理解Java类型信息(Class对象)与反射机制 深入理解Java枚举类型(enum) 深入理解Java注解类型(@Annotation) 深入理解Java并发之synchronize ...

  7. Atitit.swift 的新特性 以及与java的对比 改进方向attilax 总结

    Atitit.swift 的新特性 以及与java的对比 改进方向attilax 总结 1. defer关键字1 2. try!形式存在的"不失败"机制3 3. Guard 4 4 ...

  8. java基础之java类型

    系列文章目录 java基础之java类型 文章目录 系列文章目录 基本类型 自动类型提升 引用类型 基本类型 整型 Byte 8位 -2^7~2^7-1 默认值0 Short 16位 -2^15~2^ ...

  9. Rhyme/Spring是如何简化Java开发的(POJO、DI、AOP、模板)

    Spring是如何简化Java开发的 Spring是为了解决企业及应用的复杂性而创建的,使用spring创建的pojo对象,也就是简单的java类,可以完成原来只有重量级的EJB对象才能完成的操作. ...

最新文章

  1. 水星逆行,诸事不宜,瞬间爆炸。
  2. IT兄弟连 Java语法教程 变量1
  3. python windows下的file()
  4. 1130 Infix Expression (25 分)【难度: 一般 / 知识点: 中序遍历】
  5. Yolov4训练自己的数据集
  6. 图片作为背景并且是链接的写法(背景图片加链接)
  7. 用 ConfigMap 管理配置 - 每天5分钟玩转 Docker 容器技术(159)
  8. Illustrator2020中文版教程,如何在AI中使用蒙版来裁剪内容?
  9. mysql innodb ibd,mysql innodb 从 ibd 文件恢复表数据
  10. redux工作原理简单入门
  11. Keil C51软件的使用
  12. WinForm DevExpress使用之ChartControl控件绘制图表一——基础
  13. Boom 2 for Mac(音频助推器及均衡器) v1.6.7中文激活版
  14. AD快捷键,及一些基本操作设置总结
  15. linux开启路由器功能
  16. 第13节 eclipse简介
  17. python通过指定网卡发包_Python选择网卡发包及接收数据包
  18. 中国果蔬烘干机行业营销态势与竞争趋势预测报告(2022-2028年)
  19. Redist 6.2 zset的写入(源码),最后介绍一下skiplist的结构
  20. 机器学习 - 机器学习理论基础

热门文章

  1. Ubuntu安装yum失败-2
  2. 电力系统通信站和设备管理系统分析设计
  3. 【ds】HDU_1166
  4. 《Linux就该这么学》培训笔记_ch01_部署虚拟环境安装Linux系统
  5. LeetCode 21 ——合并两个有序链表
  6. 【codeforces 796A】Buying A House
  7. django 基于 form 验证 确认密码的注册
  8. 【bzoj1195】[HNOI2006]最短母串 AC自动机+状态压缩+BFS最短路
  9. 深度学习DL蒙特卡洛法平衡态分子动力学模拟并计算苯酚键值
  10. java 正则表达式 demo_JAVA正则表达式语法