有两个类:class S {
}class SS extends S
{
}然后这样写List<? extends S> list = new LinkedList<SS>();
list.add(new SS()); //这一行会报错没搞明白为什么会报错。。哪位大侠给讲讲啊谢谢了。/。
}class SS extends S
{
}然后这样写List<? extends S> list = new LinkedList<SS>();
list.add(new SS()); //这一行会报错没搞明白为什么会报错。。哪位大侠给讲讲啊谢谢了。/。
看一下JDK里的API就明白了.
list.add(new SS());
你new linklist的时候 泛型用SS这个儿子 可是add却另外一个 虽然父亲同一个 毕竟2个儿子 两码事情 搞到一起做什么
}class B extends C{
}A 跟B 有关系吗???他们只跟 C 有关系 A跟B 却一点关系都没有
是bounded wildcard(可以翻译成绑定通配符吧)的一个例子其中的?代表未知类型,这里的未知类型呢又是S的子类型(注意虽然是子类型,它也可以是S本身,或其任何子类,非字面extends含义),这里S呢就是通配符的上绑定(upper bound)而这里为什么不能加SS呢?
? extends S -- 一个S的未知子类型. 既然我们不知道它到底是什么类型,我们也就不知道它是否是SS的超类型,它可能是SS的超类型也可能不是,所以这里传入一个SS是不安全的。
学习。。
如果按照这样来说的话
那这儿:List<S> list=new ArrayList<S>();
list.add(new SS());岂不是add()什么类型都不对?
那也就是说:List<S> list=new ArrayList<S>();
这样写实完全没有意义的????
那这个呢List<? super S> 这个表示下绑定?
S在这里是lower bound
这个语法 ? super T
表示一个身为T超类型的未知类型,这里的超类型也可以是T本身,因为这里的超类型关系是reflexive的(反身性)和extends一样
list.add(new SS()); 我的意思是:
list.add(new SS()); 这个add的时候,放SS时不正确的,
那该放add什么类型的呢?
或者说是List<? extends S> list = new LinkedList<SS>();这种写法有问题??
谢谢解答 呵呵
我所知道的bounded wildcard也是wildcard的一个用处是public void foo(List<? extends S> list) {
}这样一个方法可以接受List<SS>类型的实参
而不使用wildcardpublic void foo(List<S> list) {
}就不能接受List<SS>类型的实参
至于这个
List<? extends S> list = new LinkedList<SS>();
list貌似是不能add任何类型了
dracularking其实已经讲解得很清楚了.List<? extends S> list = new LinkedList<SS>();
这样的list是不能进行add操作的, 因为加任何类型都属于不安全的.
可以用将list强转, 然后进行add.
而是super的话, 因为上限已经确定, 所以可以进行add.
怎么强转呢?下面两种都是编译有问题的,类型不兼容
List<? super S> list = new LinkedList<SS>();
List<S> list = new LinkedList<SS>();
List<? extends Fruit> list = new ArrayList<Apple>();
//list.add(new Apple());Error
//list.add(new Fruit());Error
List<? super Fruit> list = new ArrayList<Apple>();
list.add(new Apple());//可以
list.add(new Fruit());//可以
List<? extends Fruit> list = new ArrayList<Apple>();
list中为什么不能加入Fruit类和Fruit类的子类呢,原因是这样的
List<? extends Fruit>表示上限是Fruit,下面这样的赋值都是合法的
List<? extends Fruit> list1 = new ArrayList<Fruit>();
List<? extends Fruit> list2 = new ArrayList<Apple>();
List<? extends Fruit> list3 = new ArrayList<Jonathan>();
如果List<? extends Fruit>支持add方法的方法合法的话
list1可以add Fruit和所有Fruit的子类
list2可以add Apple和所有Apple的子类
list3可以add Jonathan和所有Jonathan的子类
这样的话,问题就出现了
List<? extends Fruit>所应该持有的对象是Fruit的子类,而且具体是哪一个
子类还是个未知数,所以加入任何Fruit的子类都会有问题,因为如果add Apple
的话,可能List<? extends Fruit>持有的对象是new ArrayList<Jonathan>()
Apple的加入肯定是不行的,如果 如果add Jonathan
的话,可能List<? extends Fruit>持有的对象是new ArrayList<Jonathan的子类>()
Jonathan的加入又不合法,所以List<? extends Fruit> list 不能进行add
而List<? super Fruit> list 表示list持有的对象是Fruit的父类,下限是 Fruit,所以list中add Fruit或Fruit的子类是没有问题的
怎么看来看去我都觉得搂主用一个<? extends S>来限定类型没有意义呢?<>符号在泛型中就是用来限定类型的,现在你给他一个通配的未确定的类型,有意义吗?还不如直接<S>,这样你传SS作为类型参数绝对没有问题。实在弄不明白为什么去争一个没有意义的问题。 极度搞不懂。我觉得恐怕只有11楼的特例能采用这种通配方式了,其它情况下,都没什么大的意义,顶16楼
List<? extends S> list = new LinkedList<SS>();这个让我想起一个问题
就是:public void input(List<Object> objs){
//这个方法和那个感觉有点像
//虽然这儿用的是List<Object> ,但是如果加List<String>却不行
//虽然String是Object的子类,但是List<String>却不是List<Object>的子类
//上面的感觉有点像,SS是S的子类,但是放到List中去以后也不一样了。。
}
呵呵 突然想起这个问题 但是看上面讲的 原理却是不一样的。。
当然可以强转, 比如:
List<? extends S> list = new LinkedList<SS>();
((List<SS>)list).add(new SS());
这样就能通过的.List<? super S> list = new LinkedList<SS>();
这个不通过是因为 ? super S 决定了上限就是S了, 只能是它或者它的父类可以.List<S> list = new LinkedList<SS>();
这个不通过是因为已经决定是S了, 那么后面也必须是S,它的子类父类都不行.
嗯,这样的强转竟然都是允许的
((List<S>)list).add(ss);
((List<SS>)list).add(ss);