当前位置: 代码迷 >> J2SE >> 泛型边境
  详细解决方案

泛型边境

热度:287   发布时间:2016-04-23 19:47:23.0
泛型边界
 

//类的继承结构
class Fruit{}
class Apple extends Fruit{}
class Jonathan extends Apple{}

public class SuperTypeVildcards {
         static void writeTo( LIst<? super Apple> apples){
                 apples.add(new Apple());
                 apples.add(new Jonathan())
                 // Error
                 apples.add(new Fruit());
         }
}

 《Java编程思想》有关这段代码是这样描述的:参数Apple是Apple的某种基类型的List,这样你就知道向其中添加Apple或Apple的子类型是安全的。
   而根据理解 List< ? super Apple> 表示的应该是List中持有的是Apple的基类。根据我的想法,第8,9行应该是错误的,而第11行才是正确的。
    看了半天也不太懂书里面关于边界的描述。希望能得到解答
           

------解决思路----------------------
举个例子:
假如有一个继承体系:Object <- Plant <- Fruit <- Apple <- Jonathan,通配符是? super Apple,Apple是下界,?是Apple的某种父类型,那么Apple及其子类一定是?类型, 所以你可以加入Apple和Jonathan类型,但是你不可以加入Fruit,因为通配符只是说是Apple的某种父类型,你怎么知道是Fruit还是Plant还是Object?
行了,自己也快晕了...
------解决思路----------------------
引用:
举个例子:
假如有一个继承体系:Object <- Plant <- Fruit <- Apple <- Jonathan,通配符是? super Apple,Apple是下界,?是Apple的某种父类型,那么Apple及其子类一定是?类型, 所以你可以加入Apple和Jonathan类型,但是你不可以加入Fruit,因为通配符只是说是Apple的某种父类型,你怎么知道是Fruit还是Plant还是Object?
行了,自己也快晕了...


接着楼上补充一下,? super Apple 表明泛型是Apple或者Apple的父类,所以能够将Apple的子类安全的添加到List中(因为子类的引用能够安全的隐式转换为父类),但是,编译器没法推断出泛型和Fruit的关系,泛型有可能是Fruit的子类,不能隐式的将父类的引用转换为子类,所以编译器会报错。
------解决思路----------------------
怎么你觉得Apple和 Jonathan不是Apple类型吗?

Java的泛型是这样子实现的,先把所有对象都当作Object存起来,取出来的时候再转成相应的类型。

所以这个例子中,应该理解为所有可以转型为Apple的类,也就是Apple和他的子类。只有这些类才能放进这个容器中,当他们取出来的时候统统转为Apple类。所以fruit对象,是不能添加进去的。
如果理解成存放Apple的父类,那么系统将会不知道在取出对象的时候应该转为什么类型,因为他的父类是不确定的,(?)。

再往后,书里应该说<? extends T>的问题,恩同样的道理,你仔细体会一下,想想java泛型怎么实现的
  相关解决方案