新JEP将简化Java类型变异
来源:互联网 发布:软件系统维护合同 编辑:程序博客网 时间:2024/05/15 23:48
新的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<Product> products) {
/* Check product stock */
shoppingCart.addAll(products);
}
private void freezerSection() {
List<FrozenProduct> frozenProducts =
/* select frozen products */
;
addAllProducts(frozenProducts);
// ERROR: List<Product> expected
// List<FrozenProduct> found
}
private void addAllProducts(List<Product> products) {
/* Check product stock */
shoppingCart.addAll(products);
}
private void freezerSection() {
List<FrozenProduct> frozenProducts =
/* select frozen products */
;
addAllProducts(frozenProducts);
// ERROR: List<Product> expected
// List<FrozenProduct> found
}
当在Java中使用泛型时,并没有关于目标类型和其子类型或超类型之间兼容性的假设。换句话说,当使用泛型时,我们默认目标类型是不变的,它只接受明确的类型。
然而,在上面的例子中,我们可以看到addAllProducts方法可以处理List of Product或是其子类型。当泛型参数可以接受其目标类型或是它的任何子类型,我们就说这个类型是协变的,在Java中可以用extends表示:
private void addAllProducts(List<? extends Product> products) {
/* Check product stock */
shoppingCart.addAll(products);
}
private void freezerSection() {
List<FrozenProduct> frozenProducts =
/* select frozen products */
;
addAllProducts(frozenProducts);
// works with no problem
}
在这些例子中,接受的目标类型的变异是子类型。在一些其他例子中,目标类型的变异不是子类型,而是超类型。考虑以下的情况:
private boolean askQuestion(Predicate<String> p) {
return
p.test(
"hello"
);
}
private void applyPredicate() {
Predicate<Object> evenLength = o -> o.toString().length() % 2 == 0;
askQuestion(evenLength);
// ERROR: Predicate<String> expected
// Predicate<Object> found
}
private boolean askQuestion(Predicate<? super String> p) {
return p.test("hello");
}
private void applyPredicate() {
Predicate<Object> evenLength = o -> o.toString().length() % 2 == 0;
askQuestion(evenLength); // works with no problem
}
通配符是创建类型变异的一种非常灵活的方法,因为它允许你在不同地方对同种类型定义不同的变异。比如说,在上面的例子里我们定义addAllProducts是协变的参数,但在其他地方根据我们的需求,可以定义它为逆变或是不变的。然而缺点是必须在每个地方根据需要明确指定变异,这样会造成很多的冗余和混乱。所以新的方案应运而生。
通配符的最主要的问题是它们比开发人员通常需要的还要灵活。在Predicate<String>的例子中,我们理论上可以创建一个方法Predicate<? extends String>,然而,可以用到的用例有限(可能根本没有)。在大量情况下,只有一个类型变异有意义,为了反映出这一点,JEP 300提供了在声明泛型类型时指定默认变异的方法,而不是在实例化时指定默认变异。比如说,用了这种方案,可以使用逆变的关键字Predicate<contravariant T>来重写接口Predicate<T>,这就代表着任何时候开发人员写Predicate<String>都会被隐含地理解为Predicate<? super String>。
这个新功能的语法尚未决定,但是已经有了一些备选项:使用新的显式关键字,如Function<contravariant T, covariant R>,或遵循其他语言的先例,如Scala中的符号(Function<-T, +R>),或是C#中的较短关键字(Function<in T, out R>)。在解决语法问题之前,还需要解决一些重要的技术问题,即默认变异和通配符之间的交互,默认变异对现有代码产生的影响,以及变异类型兼容性检查的实际机制。
- 新JEP将简化Java类型变异
- 新JEP将简化Java类型变异
- 新JEP将简化Java类型变异
- Jep java表达式分析器
- 新函数式编程语言将简化GPU应用开发
- java 如何将List<objetct>类型强制转为新的List<实体类>
- Java 7新特性(七)——简化Swing
- JEP-0078
- java9新特性-JEP 269:集合类便利的工厂方法
- java 将Object类型转换为long
- JEP-公式解析器
- Jep 解析字符串数学公式
- Jep的使用
- Jep解析字符串数学公式
- sql 类型溢出,简化日期类型查询
- java中如何将Object类型转换为int类型
- java 将String类型转换成int类型
- Java中如何将int 类型转换为 Long类型
- 在虚幻UE4中不同VR头盔的FOV和分屏处理
- bzoj 2721: [Violet 5]樱花 (线性筛+质因数分解)
- ACID补充
- OD调试之总结
- CCF之俄罗斯方块(java)
- 新JEP将简化Java类型变异
- 架构师米洛:你不经意的职场坏姿势会损坏你的身体
- 7、SQL Server:sql server 获取每一个类别中值最大的一条数据
- BitmapFactory中常用的几个静态方法
- 蓝桥杯算法提高 最大乘积
- 目前我使用的build.gradle
- BZOJ 3262: 陌上花开 (CDQ分治)
- SnackBar的使用
- enumerations inherit Enum