小弟最近在学习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:俺是小白,所以请各位牛人最好讲的细一点,谢谢~~
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:俺是小白,所以请各位牛人最好讲的细一点,谢谢~~
writeExact(fruit,new Apple()); 这一句,
传入的list是fruit,则类型T 相当于 Fruit。
那么加入的对象也应该是Fruit类型的才符合。
而,Apple继承Fruit,根据向上转型,Apple转成Fruit完全没有问题啊。
不报错是应该的啊。
//Fruit是父类,Apple继承Fruit
也就是说Apple是向上转型到基类Fruit的。
这样做完全没有问题的不会楼主是隔着章节看的吧?难道看继承和多态那里没有看到过“向上转型”?
4版应该是。
这种情况下,T应该表示的是Apple类,由于Fruit是Apple的超类所以无法自动进行强制类型转换。
writeWithWildcard(apples,new Apple());
writeWithWildcard(fruit,new Apple());
这三个语句,T所表示的类都为Apple。
{
list.add(obj);
}
static List apples = new ArrayList();
static List fruit = new ArrayList();
把堆中的引用地址给了list而已。