小弟最近在学习thinking in java,看到了让人欲仙欲死的泛型一章,但是在实验作者给出来的代码时,有个地方看的不是太明白,代码如下
import java.util.*;public class GenericWriting {
static <T> void writeExact(List<T> list,T item){
list.add(item);
}

         //Fruit是父类,Apple继承Fruit
static List<Apple> apples=new ArrayList<Apple>();
static List<Fruit> fruit=new ArrayList<Fruit>();

static void f1(){
writeExact(apples,new Apple());
//writeExact(fruit,new Apple()); Error 这就是不明白的一行
}

static <T> void writeWithWildcard(List<? super T> list,T item){
list.add(item);
}

static void f2(){
writeWithWildcard(apples,new Apple());
writeWithWildcard(fruit,new Apple());
}

public static void main(String[] args){ 
f1();
System.out.println(apples); //这个输出是我为了测试加的
System.out.println(fruit);
f2();
System.out.println(apples);
System.out.println(fruit);
}
}按照作者的意思,writeExact()这个方法应该不允许将Apple放置到List<Fruit>中,也就是取消注释,编译器应该直接报错(根据我看了一半的感觉来看,如果无法编译的,作者才会把它注释掉,反之只会进行说明),但是我取消掉注释后,编译器照样运行,而且可以将Apple放到List<Fruit>中,我研究了半天上下文,发现跟上下文要表达的意思不符,所以求牛人讲解一下~~
P.S:俺是小白,所以请各位牛人最好讲的细一点,谢谢~~

解决方案 »

  1.   

    我觉得
    writeExact(fruit,new Apple()); 这一句,
    传入的list是fruit,则类型T 相当于 Fruit。
    那么加入的对象也应该是Fruit类型的才符合。
    而,Apple继承Fruit,根据向上转型,Apple转成Fruit完全没有问题啊。
    不报错是应该的啊。
      

  2.   

    但是根据书上bruce他老人家的说法,虽然形式上这样是没问题的,但是编译器不接受这种“不安全”的行为,至少从上下文的理解来说是这样,完全糊了啊~@_@
      

  3.   

    楼主仔细看了注释没有呢?
    //Fruit是父类,Apple继承Fruit 
    也就是说Apple是向上转型到基类Fruit的。
    这样做完全没有问题的不会楼主是隔着章节看的吧?难道看继承和多态那里没有看到过“向上转型”?
      

  4.   

    thinking in java 3版不是java5
    4版应该是。
      

  5.   

    writeWithWildcard(fruit,new Apple());  这句也出错
      

  6.   

    楼主不明白的那个语句,应该换成writeExact(apples,new Fruit());
    这种情况下,T应该表示的是Apple类,由于Fruit是Apple的超类所以无法自动进行强制类型转换。
      

  7.   

    writeExact(apples,new Apple());
    writeWithWildcard(apples,new Apple()); 
    writeWithWildcard(fruit,new Apple()); 
    这三个语句,T所表示的类都为Apple。
      

  8.   

    编译之后你的T均为object,经过反编译:    static void writeExact(List list, Object obj)
        {
            list.add(obj);
        }
        static List apples = new ArrayList();
        static List fruit = new ArrayList();
      

  9.   

    我觉得不存在向下或者向上转换,也就是父类(object)引用指向子类,
    把堆中的引用地址给了list而已。