黑马程序员技术交流社区

标题: 泛型中这条语句为什么会错? [打印本页]

作者: liuzhming    时间: 2013-7-23 18:58
标题: 泛型中这条语句为什么会错?
在下面的代码中为什么最后一句会编译失败?
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
public class GenericTest<T>
{
        private T foo;
        public T getFoo()
        {
                return foo;
        }

        public void setFoo(T foo)
        {
                this.foo = foo;
        }
       
        public static void main(String[] args)
        {
                GenericTest<? extends List> ge = null;
                ge = new GenericTest<ArrayList>();
                ge = new GenericTest<LinkedList>();
               
                GenericTest<? super List> ge2 = null;
                ge2 = new GenericTest<Object>();
               
                GenericTest<String> ge3 = new GenericTest<String>();
                ge3.setFoo("hello world");
               
                GenericTest<?> ge4 = ge3;
                System.out.println(ge4.getFoo());
                ge4.setFoo(null);
                System.out.println(ge4.getFoo());
            ge4.setFoo("welcome");//在前面可以将null传给它,为什么这条语句会失败呢?
        }
}
作者: yinjiek    时间: 2013-7-23 19:23
  ge4.setFoo(null);
                 System.out.println(ge4.getFoo());
             ge4.setFoo("welcome");//
已经赋值为空了再赋值“welcome”当然编译出错了,字符串具有不变性;
作者: 李江    时间: 2013-7-23 19:52
问题错误之处在于通配符的使用:
注意两点:
1.通配符修饰的泛型不能用来直接创建变量对象。
2.通配符修饰相当于声明了一种变量,它可以作为参数在方法中传递。
  这么做带来的好处就是我们可以将应用于包含某些数据类型的列表的方法也应用到包含其子类型的列表中。
  相当于可以在列表中用到一些面向对象的特性。
GenericTest<?> ge4 = ge3;//错在此句
改为:
GenericTest<String> ge4 = ge3;
作者: 张强1    时间: 2013-7-23 20:04
我觉的也像是通配符有问题
GenericTest<?> ge4 = ge3;
应该是String
作者: 张yy    时间: 2013-7-23 20:34
首先,要去了解泛型使用通用类型通配符的具体规则。

当使用A<?>这种形式来定义泛型类型的时候,称之为通配符定义,
而使用通配符声明的名称实例化的对象不能对其加入新的信息,只能获取或删除,即get()或者remove();
也就是说使用GenericTest<?> ge4 = ge3;
这时候ge4. set()方法是不能被调用的。
然后ge4.setFoo(null);的作用是将里面的信息值空,也就是起到了删除的功能,
所以你的代码中能够使用ge4.setFoo(null);而不能调用ge4.setFoo("welcome");

要想调用ge4.setFoo("welcome");的话,就不能再这里使用通配符声明 GenericTest<?> ge4 = ge3;
改为使用 GenericTest<String> ge4 = ge3;

作者: toShareBeauty    时间: 2013-7-23 20:36
本帖最后由 toShareBeauty 于 2013-7-23 20:38 编辑

楼主好问题,这个问题已经超出我对泛型的认识,我一直认为这是可以的,但是编译器确实报错了。经过查资料得到下面结果。主要是因为在使用 泛型通配符的时候,编译器限制了一些东西。为什么这么限制,因为为了强制的让你用了泛型就不能用强制类型转换。



按照上面的说法,楼主的用法只能使用get不能使用set,当然 null 不同,set null 是移除信息。




作者: の放下执著    时间: 2013-7-24 03:10
首先,定义了一个泛型类GenericTest<T>,然后  GenericTest<String> ge3 = new GenericTest<String>();GenericTest<?> ge4 = ge3;
相当于GenericTest<?> ge4 = new GenericTest<String>();对象中的类型是string类型。引用ge4也指向堆内存中的GenericTest<String>();“?”是通配符,表示类型不确定。调用ge4.setFoo("welcome");会失败,我觉得有点像多态中:父类引用不能调用子类对象特有的方法   一样。
改为:GenericTest<String> ge4 = ge3;




欢迎光临 黑马程序员技术交流社区 (http://bbs.itheima.com/) 黑马程序员IT技术论坛 X3.2