在看head first java中的第十六章时,在我是编译器这一栏目中遇到这个问题的:有一个Animal类(抽象类),一个Dog类。明显Dog继承了Animal类。然后有:ArrayList<Animal> ani = new ArrayList<Animal>();
ArrayList<Dog> dog = new ArrayList<Dog>();这两个肯定是正确的。但是下面两个:ArrayList<Animal> ani = new ArrayList<Dog>();    (1)
ArrayList<Dog> dog = new ArrayList<Animal>();    (2)我试了一下,eclipse都报错了。我的疑惑从下面推理得的:Animal ani = new Dog();                           (3)
Dog dog = new Animal();                           (4)第一个明显是对的,因为可以用子类来初始化父类;第二个不对是因为不存在Animal对象。
回到上一个问题:疑惑一:ArrayList<Animal> ani = new ArrayList<Dog>();我觉得是对的。这不就是(3)的变种吗?无非是装在ArrayList容器中。
疑惑二:第二个错误也是由于ArrayList<Animal>中Animal不能实例化引起的吗?经过尝试,我把Animal改为非抽象类,但是上面的错误一个都没有消失。eclipse提示是类型不匹配:不能将ArrayList<Dog>转化为ArrayList<Animal>。希望明白这是怎么回事的人解答一下,谢谢~java

解决方案 »

  1.   

    补充一个问题:ArrayList<T>只能用T初始化吗?当然,除了ArrayList<? extends T>这么用的(话说这个能实现泛型,但是为什么不直接使用ArrayList<T或者T的子类>这样的方式呢?这不是更方便吗?)
      

  2.   

    ArrayList<Dog>和ArrayList<Animal>并不是像Dog类和Animal类那样具有继承关系,他们之间的关系应该是平行的,故不能使用ArrayList<Animal> ani = new ArrayList<Dog>();这种类似多态的方法来做。
    建议你再看看向上转型和向下转型的知识,应该就差不多了。
      

  3.   

    这个跟转型没有什么关系。
    ArrayList<Animal> ani = new ArrayList<Dog>();这个肯定是行不通的。
    你声明了一个集合可以存Animal,所以猪啊猫啊狗啊,只要继承了Animal都都可以往里面存。
    而你后面new的集合只能存dog,猪和猫能存进去吗?
    所以这种写法根本行不通
    所以,在使用泛型的时候,只要两边都用了,两边就必须一样
    为了保持程序的兼容性,只在一边使用泛型却没有错。
      

  4.   

    补充一下:
    你使用通配符的话,虽然看上去两边写法不一样,其实本质是一样的
    像这样是可以的
    ArrayList< ? extends Animal> al = new ArrayList<dog>();
      

  5.   

    因为Java中,泛型不是协变的。