1700447368
//Number的子类型(包括Number类型)都可以是泛型参数类型
1700447369
1700447370
List<?extends Number>ln=new ArrayList<Integer>();
1700447371
1700447372
“?extends Number”表示的意思是,允许Number所有的子类(包括自身)作为泛型参数类型,但在运行期只能是一个具体类型,或者是Integer类型,或者是Double类型,或者是Number类型,也就是说通配符只是在编码期有效,运行期则必须是一个确定类型。
1700447373
1700447374
(2)泛型不支持逆变
1700447375
1700447376
Java虽然可以允许逆变存在,但在对类型赋值上是不允许逆变的,你不能把一个父类实例对象赋值给一个子类类型变量,泛型自然也不允许此种情况发生了,但是它可以使用super关键字来模拟实现,代码如下。
1700447377
1700447378
//Integer的父类型(包括Integer)都可以是泛型参数类型
1700447379
1700447380
List<?super Integer>li=new ArrayList<Number>();
1700447381
1700447382
“?super Integer”的意思是可以把所有Integer父类型(自身、父类或接口)作为泛型参数,这里看着就像是把一个Number类型的ArrayList赋值给了Integer类型的List,其外观类似于使用一个宽类型覆盖一个窄类型,它模拟了逆变的实现。
1700447383
1700447384
泛型既不支持协变也不支持逆变,带有泛型参数的子类型定义与我们经常使用的类类型也不相同,其基本的类型关系如表7-1所示。
1700447385
1700447386
1700447387
1700447388
1700447389
注意 Java的泛型是不支持协变和逆变的,只是能够实现协变和逆变。
1700447390
1700447391
1700447392
1700447393
1700447395
编写高质量代码:改善Java程序的151个建议 建议98:建议采用的顺序是List<T>、List<?>、List<Object>
1700447396
1700447397
List<T>、List<?>、List<Object>这三者都可以容纳所有的对象,但使用的顺序应该是首选List<T>,次之List<?>,最后选择List<Object>,原因如下:
1700447398
1700447399
(1)List<T>是确定的某一个类型
1700447400
1700447401
List<T>表示的是List集合中的元素都为T类型,具体类型在运行期决定;List<?>表示的是任意类型,与List<T>类似,而List<Object>则表示List集合中的所有元素为Object类型,因为Object是所有类的父类,所以List<Object>也可以容纳所有的类类型,从这一字面意义上分析,List<T>更符合习惯:编码者知道它是某一个类型,只是在运行期才确定而已。
1700447402
1700447403
(2)List<T>可以进行读写操作
1700447404
1700447405
List<T>可以进行诸如add、remove等操作,因为它的类型是固定的T类型,在编码期不需要进行任何的转型操作。
1700447406
1700447407
List<?>是只读类型的,不能进行增加、修改操作,因为编译器不知道List中容纳的是什么类型的元素,也就无法校验类型是否安全了,而且List<?>读取出的元素都是Object类型的,需要主动转型,所以它经常用于泛型方法的返回值。注意,List<?>虽然无法增加、修改元素,但是却可以删除元素,比如执行remove、clear等方法,那是因为它的删除动作与泛型类型无关。
1700447408
1700447409
List<Object>也可以读写操作,但是它执行写入操作时需要向上转型(Up cast),在读取数据后需要向下转型(Downcast),而此时已经失去了泛型存在的意义了。
1700447410
1700447411
打个比方,有一个篮子用来容纳物品,List<T>的意思是说,“嘿,我这里有一个篮子,可以容纳固定类别的东西,比如西瓜、番茄等”。List<?>的意思是说“嘿,我也有一个篮子,我可以容纳任何东西,只要是你想得到的”。而List<Object>就更有意思了,它说“嘿,我也有一个篮子,我可以容纳所有物质,只要你认为是物质的东西就都可以容纳进来”。
1700447412
1700447413
推而广之,Dao<T>应该比Dao<?>、Dao<Object>更先采用,Desc<Person>则比Desc<?>、Desc<Object>更优先采用。
1700447414
1700447415
1700447416
1700447417
[
上一页 ]
[ :1.700447368e+09 ]
[
下一页 ]