java 泛型嵌套泛型_Java泛型简介–第6部分
java 泛型嵌套泛型
这是关于泛型的介绍性讨论的延续, 此处的先前部分可以在此处找到。
在上一篇文章中,我们讨论了关于类型参数的递归边界。 我们看到了递归绑定如何帮助我们重用了车辆比较逻辑。 在该文章的结尾,我建议当我们不够谨慎时,可能会发生类型混合。 今天我们将看到一个例子。
如果有人错误地通过以下方式创建了Vehicle的子类,则可能会发生混合:
/*** Definition of Vehicle*/
public abstract class Vehicle<E extends Vehicle<E>> implements Comparable<E> {// other methods and propertiespublic int compareTo(E vehicle) {// method implementation}
}/*** Definition of Bus*/
public class Bus extends Vehicle<Bus> {}/*** BiCycle, new subtype of Vehicle*/
public class BiCycle extends Vehicle<Bus> {}/*** Now this class’s compareTo method will take a Bus type* as its argument. As a result, you will not be able to compare* a BiCycle with another Bicycle, but with a Bus.*/
cycle.compareTo(anotherCycle); // This will generate a compile time error
cycle.compareTo(bus); // but you will be able to do this without any error
枚举不会发生这种类型的混淆,因为JVM负责子类化和为枚举类型创建实例,但是如果我们在代码中使用这种样式,则必须小心。
让我们谈谈递归边界的另一个有趣的应用。 考虑以下类别:
public class MyClass {private String attrib1;private String attrib2;private String attrib3;private String attrib4;private String attrib5;public MyClass() {}public String getAttrib1() {return attrib1;}public void setAttrib1(String attrib1) {this.attrib1 = attrib1;}public String getAttrib2() {return attrib2;}public void setAttrib2(String attrib2) {this.attrib2 = attrib2;}public String getAttrib3() {return attrib3;}public void setAttrib3(String attrib3) {this.attrib3 = attrib3;}public String getAttrib4() {return attrib4;}public void setAttrib4(String attrib4) {this.attrib4 = attrib4;}public String getAttrib5() {return attrib5;}public void setAttrib5(String attrib5) {this.attrib5 = attrib5;}
}
如果我们要创建此类的实例,则可以执行以下操作:
MyClass mc = new MyClass();
mc.setAttrib1("Attribute 1");
mc.setAttrib2("Attribute 2");
上面的代码创建该类的实例并初始化属性。 如果我们可以在此处使用方法链接 ,那么我们可以编写:
MyClass mc = new MyClass().setAttrib1("Attribute 1").setAttrib2("Attribute 2");
显然比第一个版本好得多。 但是,要启用这种方法链接,我们需要通过以下方式修改MyClass :
public class MyClass {private String attrib1;private String attrib2;private String attrib3;private String attrib4;private String attrib5;public MyClass() {}public String getAttrib1() {return attrib1;}public MyClass setAttrib1(String attrib1) {this.attrib1 = attrib1;return this;}public String getAttrib2() {return attrib2;}public MyClass setAttrib2(String attrib2) {this.attrib2 = attrib2;return this;}public String getAttrib3() {return attrib3;}public MyClass setAttrib3(String attrib3) {this.attrib3 = attrib3;return this;}public String getAttrib4() {return attrib4;}public MyClass setAttrib4(String attrib4) {this.attrib4 = attrib4;return this;}public String getAttrib5() {return attrib5;}public MyClass setAttrib5(String attrib5) {this.attrib5 = attrib5;return this;}
}
然后我们将可以对此类的实例使用方法链接。 但是,如果我们想在涉及继承的地方使用方法链接,那么事情就会变得混乱:
public abstract class Parent {private String attrib1;private String attrib2;private String attrib3;private String attrib4;private String attrib5;public Parent() {}public String getAttrib1() {return attrib1;}public Parent setAttrib1(String attrib1) {this.attrib1 = attrib1;return this;}public String getAttrib2() {return attrib2;}public Parent setAttrib2(String attrib2) {this.attrib2 = attrib2;return this;}public String getAttrib3() {return attrib3;}public Parent setAttrib3(String attrib3) {this.attrib3 = attrib3;return this;}public String getAttrib4() {return attrib4;}public Parent setAttrib4(String attrib4) {this.attrib4 = attrib4;return this;}public String getAttrib5() {return attrib5;}public Parent setAttrib5(String attrib5) {this.attrib5 = attrib5;return this;}
}public class Child extends Parent {private String attrib6;private String attrib7;public Child() {}public String getAttrib6() {return attrib6;}public Child setAttrib6(String attrib6) {this.attrib6 = attrib6;return this;}public String getAttrib7() {return attrib7;}public Child setAttrib7(String attrib7) {this.attrib7 = attrib7;return this;}
}/*** Now try using method chaining for instances of Child* in the following way, you will get compile time errors.*/
Child c = new Child().setAttrib1("Attribute 1").setAttrib6("Attribute 6");
这样做的原因是,即使Child从其父级继承了所有的setter,所有这些setter方法的返回类型也都是Parent类型,而不是Child类型。 因此,第一个设置器将返回类型为Parent的引用,调用setAttrib6会导致编译错误,因为它没有任何此类方法。
我们可以通过在Parent上引入通用类型参数并在其上定义递归绑定来解决此问题。 它的所有子项从其扩展时都将自己作为类型参数传递,从而确保setter方法将返回其类型的引用:
public abstract class Parent<T extends Parent<T>> {private String attrib1;private String attrib2;private String attrib3;private String attrib4;private String attrib5;public Parent() {}public String getAttrib1() {return attrib1;}@SuppressWarnings("unchecked")public T setAttrib1(String attrib1) {this.attrib1 = attrib1;return (T) this;}public String getAttrib2() {return attrib2;}@SuppressWarnings("unchecked")public T setAttrib2(String attrib2) {this.attrib2 = attrib2;return (T) this;}public String getAttrib3() {return attrib3;}@SuppressWarnings("unchecked")public T setAttrib3(String attrib3) {this.attrib3 = attrib3;return (T) this;}public String getAttrib4() {return attrib4;}@SuppressWarnings("unchecked")public T setAttrib4(String attrib4) {this.attrib4 = attrib4;return (T) this;}public String getAttrib5() {return attrib5;}@SuppressWarnings("unchecked")public T setAttrib5(String attrib5) {this.attrib5 = attrib5;return (T) this;}
}public class Child extends Parent<Child> {private String attrib6;private String attrib7;public String getAttrib6() {return attrib6;}public Child setAttrib6(String attrib6) {this.attrib6 = attrib6;return this;}public String getAttrib7() {return attrib7;}public Child setAttrib7(String attrib7) {this.attrib7 = attrib7;return this;}
}
请注意,我们已经明确地施放此为T类型,因为编译器不知道这种转换是否是可能的,即使它是因为牛逼的定义是由父<T>界。 同样,由于我们将对象引用转换为T ,因此编译器将发出未经检查的警告。 为了抑制这种情况,我们在设置器上方使用了@SuppressWarnings(“ unchecked”) 。
经过上述修改,这样做是完全有效的:
Child c = new Child().setAttrib1("Attribute 1").setAttrib6("Attribute 6");
当以这种方式编写方法设置器时,我们应注意不要将递归边界用于其他任何目的,例如从父级访问子级状态,因为这会使父级暴露于其子类的内部细节,并最终破坏封装。
通过这篇文章,我完成了泛型的基本介绍。 我在本系列中没有讨论太多的事情,因为我认为它们已经超出了介绍的范围。
直到下一次。
翻译自: https://www.javacodegeeks.com/2014/07/an-introduction-to-generics-in-java-part-6.html
java 泛型嵌套泛型
java 泛型嵌套泛型_Java泛型简介–第6部分相关推荐
- java 接口的泛型方法_Java泛型/泛型方法/通配符/泛型接口/泛型泛型擦出
从JDK1.5以后引入了三大常用新特性:泛型.枚举(enum).注解(Annotation).其中JDK1.5中泛型是一件非常重要的实现技术,它可以帮助我们解决程序的参数转换问题.本文为大家详细介绍一 ...
- java 泛型集合应用_Java泛型集合的应用和方法
展开全部 泛型(Generic type 或者 generics)是对 Java 语言的类型系统的一种扩展,以支持创建可以62616964757a686964616fe78988e69d8331333 ...
- java 怎么为泛型参数赋值_Java泛型讲解
1. 概述在引入泛型之前,Java类型分为原始类型.复杂类型,其中复杂类型分为数组和类.引入范型后,一个复杂类型 就可以在细分成更多的类型. 例如原先的类型List,现在在细分成List, List等 ...
- java泛型常用特点_Java泛型详解
对java的泛型特性的了解仅限于表面的浅浅一层,直到在学习设计模式时发现有不了解的用法,才想起详细的记录一下. 本文参考java 泛型详解.Java中的泛型方法. java泛型详解 1. 概述 泛型在 ...
- java泛型与接口_Java泛型用于方法,类和接口
什么是泛型? 型就是数据类型参数化.就是说原本定死的数据类型像方法中的形参一样,数据是不确定的,使用的时候由人传进去,泛型就是这样,数据类型不确定了.使用的时候再确定就可以了. 泛型的特点 是JDK1 ...
- java参数传入泛型类型_Java 泛型(参数化类型)
Java 泛型 Java 泛型(generics)是 JDK 5 中引入的一个新特性, 泛型提供了编译时类型安全检测机制,该机制允许程序员在编译时检测到非法的类型. 泛型的本质是参数化类型,也就是说所 ...
- java 泛型集合示例_Java 泛型(示例代码)
1.泛型的由来 我们先看下面这段代码: 报错信息如下: 也就是 集合中第二个数据是 Integer,但是我们取出来的时候将其转换为 String 了,所以报错. 那么这个如何解决呢? ①.我们在遍历的 ...
- java泛型详解_Java泛型详解(透彻)
定义 Java中的泛型在JavaSE5中引入. 所谓泛型,即参数化类型.就是说,类型是以参数的方式传入泛型类. 例如: ArrayList aaryList = new ArrayList(); 那么 ...
- 描述java泛型引入原则_Java/泛型的类型擦除/README.md · oslo/LearningNotes - Gitee.com
前言 Java 泛型(Generic)的引入加强了参数类型的安全性,减少了类型的转换,但有一点需要注意:Java 的泛型在编译器有效,在运行期被删除,也就是说所有泛型参数类型在编译后都会被清除掉,看下 ...
- java super extend 区别_Java泛型中extends和super的区别
extends T>和 super T>是Java泛型中的"通配符(Wildcards)"和"边界(Bounds)"的概念. extends T&g ...
最新文章
- leetcode算法题--矩阵区域和
- node exprass安装运行实例
- CF1096E The Top Scorer
- gogs可以自动化部署吗_Git-WebHook 自动化部署工具 - 支持Github / GitLab / Gogs / GitOsc...
- java 中map_Java中Map集合
- linux 判断网卡是否异常_如何判断linux网卡故障?
- Python获取命令行参数
- 【ElasticSearch】Es 源码之 Discovery DiscoveryModule ZenDiscovery 源码解读
- MYSQL索引和权限管理
- Eclipse安装WindowsBuilder失败解决方法
- Part.0模糊集表示方法
- 智能会议系统集成解决方案
- 吉客云与金蝶云星空集成方案(吉客云主管库存)
- html中图片旋转木马,教你怎么用CSS3做一个图片的旋转木马效果
- ARP报文的存入条件和回复条件
- Android Studio MAC M1 安装模拟器
- XZ压缩最新压缩率之王
- MATLAB上的GPU加速计算
- 江湖中常说的“网格交易法”到底是什么?
- 美团/叮咚/盒马/淘鲜达/百联到家autojs脚本学习案例
热门文章
- jzoj1265-Round Numbers【数位统计】
- codeforces773 D. Perishable Roads(思维+最短路)
- E - Escape from the Island(最短路+dp)
- 【记忆化搜索】【线性化DP】滑雪 (ssl 1202/luogu 1434/pku 1088)
- Wannafly挑战赛24
- Scala与Java差异(三)之函数
- 深入源码分析Java线程池的实现原理
- Java中的6颗语法糖
- 花了100多去KTV不是唱歌,竟然是……
- idea tomcat部署web项目_项目开发之部署帆软到Tomcat服务一