《Java 核心技术 卷1》 笔记 第12章 泛型程序设计(7)泛型类型的继承限定
12.7 泛型类型的继承规则
下面一段程序展示了父子泛型对应的类互相赋值的过程。猜一猜1、2这两句哪句是正确的呢?还是都不正确?
❤🧡💛💚💙💜🤎🖤❤🧡💛💚💙💜🤎🖤❤🧡💛💚💙💜🤎🖤
public class Main { public static void main(String[] args) { Main solution = new Main(); Son a = new Son(); Son b = new Son(); Pair ancient = new Pair(a,b); Pair inheritor = new Pair(a,b); ancient = inheritor;//1 inheritor = ancient;//2 }}class Parent{ }class Son extends Parent{ }class Pair{ T first; T second; public Pair(T first,T second){ this.first = first; this.second = second; }}
❤🧡💛💚💙💜🤎🖤❤🧡💛💚💙💜🤎🖤❤🧡💛💚💙💜🤎🖤
结果(都不正确):
🚗🚓🚕🛺🚙🚌🚐🚎🚑🚒🚚🚛🚜🚘🚔🚖🚍🦽🦼🛹🚲🛴🛵🏍
🚗🚓🚕🛺🚙🚌🚐🚎🚑🚒🚚🚛🚜🚘🚔🚖🚍🦽🦼🛹🚲🛴🛵🏍
原因分析:泛型类型无论是否父子类,相同类给予的不同泛型间都不可以相互赋值,否则违背了泛型的初衷----类型检查
如果一定要进行赋值呢?我们前面提到过两个重要的点:
📕 泛型是用于辅助编译器检查的,不使用泛型只要保证程序正确是可以运行的
📗 使用泛型的变量,赋值给不使用泛型的变量会产生警告(本步骤无法检查泛型)
所以我们可以在中间这一步,不使用泛型,以回避父子类问题,如下:
❤🧡💛💚💙💜🤎🖤❤🧡💛💚💙💜🤎🖤❤🧡💛💚💙💜🤎🖤
public class Main { public static void main(String[] args) { Main solution = new Main(); Son a = new Son(); Son b = new Son(); Pair ancient = new Pair(a,b); Pair inheritor = new Pair(a,b);// Pair center = inheritor;//1// ancient = center; Pair center2 = ancient;//2 inheritor = center2; System.out.println(inheritor.toString()); System.out.println(ancient.toString()); }}class Parent{ }class Son extends Parent{ }class Pair{ T first; T second; public Pair(T first,T second){ this.first = first; this.second = second; }@Override public String toString() { return "Pair{" + "first=" + first + ", second=" + second + '}'; }}
❤🧡💛💚💙💜🤎🖤❤🧡💛💚💙💜🤎🖤❤🧡💛💚💙💜🤎🖤
运行结果:
🚗🚓🚕🛺🚙🚌🚐🚎🚑🚒🚚🚛🚜🚘🚔🚖🚍🦽🦼🛹🚲🛴🛵🏍
🚗🚓🚕🛺🚙🚌🚐🚎🚑🚒🚚🚛🚜🚘🚔🚖🚍🦽🦼🛹🚲🛴🛵🏍
这样是可以运行的,解决了报错问题。
然后会产生警告。于是我们发现泛型的类型检查约束在赋值的这两步转换中,失效了。我们无法确定赋值这个操作是安全的,也无法保证进行赋值的两个变量的泛型间,具有父子关系。
怎么能既完成类型检查,又不让泛型产生报错呢?
12.8 通配符类型
12.8.1 通配符的类型限定
(1)子类限定
子类类型赋值给父类类型,如下:
❤🧡💛💚💙💜🤎🖤❤🧡💛💚💙💜🤎🖤❤🧡💛💚💙💜🤎🖤
public class Main { public static void main(String[] args) { Main solution = new Main(); Son a = new Son(); Son b = new Son(); Pair ancient = new Pair(a,b); Pair inheritor = new Pair(a,b);// Pair center = inheritor;//1// ancient = center; Pair center2 = ancient;//2 inheritor = center2; System.out.println(inheritor.toString()); System.out.println(ancient.toString()); }}class Parent{ }class Son extends Parent{ }class Pair{ T first; T second; public Pair(T first,T second){ this.first = first; this.second = second; }@Override public String toString() { return "Pair{" + "first=" + first + ", second=" + second + '}'; }}
❤🧡💛💚💙💜🤎🖤❤🧡💛💚💙💜🤎🖤❤🧡💛💚💙💜🤎🖤
(2)父类限定
同样的,如果需要把父类类型赋值给子类类型,可使用 super,如下:
❤🧡💛💚💙💜🤎🖤❤🧡💛💚💙💜🤎🖤❤🧡💛💚💙💜🤎🖤
public class Main { public static void main(String[] args) { Main solution = new Main(); Parent a = new Parent(); Parent b = new Parent();Son c = new Son(); Son d = new Son(); Pair ancient = new Pair(a,b); Pair inheritor = new Pair(c,d); inheritor = ancient; }}class Parent{ }class Son extends Parent{ }class Pair{ T first; T second; public Pair(T first,T second){ this.first = first; this.second = second; }@Override public String toString() { return "Pair{" + "first=" + first + ", second=" + second + '}'; }}
❤🧡💛💚💙💜🤎🖤❤🧡💛💚💙💜🤎🖤❤🧡💛💚💙💜🤎🖤
总结:
1. 子类赋值给父类,使用 限定泛型
2. 父类赋值给子类,使用 限定泛型
相关内容:选择 《Java核心技术 卷1》查找相关笔记
评论🌹点赞👍收藏✨关注👀,是送给作者最好的礼物,愿我们共同学习,一起进步
如果对作者发布的内容感兴趣,可点击下方关注公众号 钰娘娘知识汇总 查看更多作者文章哦!