JAVA泛型

连线北海
连线北海
连线北海
201
文章
6
评论
2018年6月19日12:03:57 评论 529 97字阅读0分19秒

误区

List<String> ls =​​ new​​ ArrayList<String>();​​ // 1

List<Object> lo = ls;​​ // 2​​ 

lo.add(new​​ Object());​​ // 3

String s = ls.get(0);​​ // 4: Attempts to assign an Object to a String!

上面例子看到第二行的时候,很多人会认为表达式成立,因为我们认为StringObject的子类,那么List<String>也应该是List<Object>的子集合;可看完整段程序,我们又疑惑了,怎么能将Object直接放进去List<String>(这里通过List<Object>访问List<String>),这样的话,List<String>将不再只存放String对象了,这怎么行?因此在程序第二行,编译器会给出错误提示。

PECS

Producer Extends Consumer Super

例子

  • Fruit类和它的派生类Apple

class​​ Fruit​​ { }

class​​ Apple​​ extends​​ Fruit​​ { }

  • 最简单的容器:Plate

class​​ Plate<T> {​​ 

private​​ T item;​​ 

public​​ Plate(T t) {​​ 

 item = t;​​ 

 }​​ 

public​​ void​​ set(T t) {​​ 

 item = t;​​ 

 }​​ 

public​​ T​​ get() {​​ 

return​​ item;​​ 

 }​​ 

}

  • 定义一个水果盘子,逻辑上水果盘子当然可以装苹果,可事实上它却发生了异常。

Plate<Fruit> p =​​ new​​ Plate<Apple>(new​​ Apple()); // error​​ 

Type mismatch: cannot convert from Plate<Apple>​​ to Plate<Fruit>

结论:就算容器装的东西之间有继承关系,但容器之间是没有继承关系的

泛型

上界通配符​​ Upper Bounds Wildcards

Plate<?​​ extends Fruit>

意思是:一个能放水果以及一切是水果派生类的盘子

Plate<? extends Fruit>Plate<Fruit>以及Plate<Apple>的基类

Plate<?​​ extends Fruit> p =​​ new​​ Plate<Apple>(new​​ Apple());

上面的例子是成立的。

https://upload-images.jianshu.io/upload_images/3251891-4aab0685b5c2d4d0.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/600

继承体系图

 

下界通配符​​ Lower Bounds Wildcards

Plate<?​​ super​​ Fruit>

意思是与上界通配符相反的概念:一个能放水果以及一切是水果基类的盘子

Plate<? super Fruit>是Plate<Fruit>的基类,但不是Plate<Apple>的基类。

https://upload-images.jianshu.io/upload_images/3251891-66f55f072aa87e68.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/600

继承体系图

上下界通配符的副作用

边界让Java不同泛型之间的转换更容易,但是也会让容器的部分功能可能失效

上界<? extends T>

造成结果:不能往里存,只能往外取。

<? extends Fruit>会使往盘子里放东西的set( )方法失效。但取东西get( )方法还有效。

对于Plate​​ <? extends Fruit>编译器只知道容器Plate内是Fruit或者它的派生类,但具体是什么类型不知道。用Plate<Apple>赋值给容器以后,容器没有被标上苹果而是标上一个占位符:CAP#1,来表示捕获一个FruitFruit子类,具体是什么类不知道然后无论是想往容器里插入Apple或者Banana或者Fruit编译器都不知道能不能和这个CAP#1匹配,所以都不允许。

 

下界<? super T>

不影响往里存,但往外取只能放在Object对象里

 

<T extends Fruit>与<? extends Fruit>区别

<T extends Fruit>作用于方法或者类上,而​​ <? extends Fruit>​​ 则不可以。

 

 

 

 

https://www.jianshu.com/p/276699764aa2

 

https://www.cnblogs.com/VergiLyn/p/6349601.html

https://segmentfault.com/q/1010000002489030

 

https://garygregory.wordpress.com/2016/11/29/understanding-java-generics-super-and-extends/

 

https://dzone.com/articles/how-do-generic-subtypes-work

http://www.codejava.net/java-core/collections/how-to-write-generic-classes-and-methods-in-java

https://blog.csdn.net/qq_27093465/article/details/73249434

 

https://www.cnblogs.com/Michaelwjw/p/5881875.html

 

weinxin
微信公众号
分享IT信息技术、北海生活的网站。提供北海本地化的信息技术服务。
连线北海
  • 本文由 发表于 2018年6月19日12:03:57
  • 除非特殊声明,本站文章均为原创,转载请务必保留本文链接
Java库之Lombok的妙用 JAVA编程

Java库之Lombok的妙用

Lombok是目前比较流行的Java库,Lombok能以简单的注解形式来简化Java代码,提高开发人员的开发效率,免去额外的getter或equals等方法,降低由于修改引起的维护成本,Lombok在...
【进阶】-Java读写文件锁 JAVA编程

【进阶】-Java读写文件锁

众所周知,Java中锁的概念是非常重要的,锁可以保证资源的安全可控,恰当使用锁即可使得资源高效利用,又能保证线程的安全访问,编程中在读取文件的时候常常碰到文件锁的使用,本文简单阐述文件锁在Java中的...
【基础】-Java访问控制 JAVA编程

【基础】-Java访问控制

访问控制 访问级别修饰符的作用是确定其他类是否可以使用特定字段或调用特定方法。 访问控制有两个级别: 在顶层级别 - public或package-private。 在成员级别 - public,pr...
匿名

发表评论

匿名网友 填写信息

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen: