调用方法已经实现功能了 不理解为什么AnimalPlay类里的方法返回值接收不了

调用方法已经实现功能了 不理解为什么AnimalPlay类里的方法返回值接收不了

public abstract class Animal{
    //按任务要求实现该类
    private String name;

    public Animal(){}

    public Animal(String name) {
        this.setName(name);
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public abstract void game();
}


public class Dog extends Animal{
    //按任务要求实现该类

    public Dog(){}

    public Dog(String name){
        super.setName(name);
    }

    @Override
    public void game() {
        System.out.println("小狗"+super.getName()+"在做游戏!");
    }
}


public class Cat extends Animal {
    public Cat(){}

    public Cat(String name){
        super.setName(name);
    }

    @Override
    public void game() {
        System.out.println("小猫"+super.getName()+"在做游戏!");
    }
}


public class AnimalPlay {
    public List<? extends Animal> animalGame(List<Animal> animal){
        for (Animal item:animal) {
            item.game();
        }
        return animal;
    }
}


public class Test {
    public static void main(String[] args) {
        //定义List并添加Dog类对象
//定义List并添加Cat类对象
        List<Animal> animals = new ArrayList<>();

        Dog dogBD = new Dog("巴迪");
        Dog dogDD = new Dog("豆豆");
        Cat catHH = new Cat("花花");
        Cat catFF = new Cat("凡凡");

        animals.add(dogBD);
        animals.add(dogDD);
        animals.add(catHH);
        animals.add(catFF);

        //使用AnimalPlay类的方法,按照演示效果输出内容
        AnimalPlay ap = new AnimalPlay();
        List<Animal> list = ap.animalGame(animals);






    }
}
           

正在回答 回答被采纳积分+1

登陆购买课程后可参与讨论,去登陆

1回答
好帮手慕小蓝 2024-05-22 14:50:13

同学你好,这是因为泛型约束的范围导致的,我们可以先分析一下同学代码中两个泛型的范围:

public List<? extends Animal> animalGame(List<Animal> animal)

在这个方法的参数列表中,约定了List中可以存储任意Animal类型的对象。由于Java支持多态的特性,所以此处可以是Animal或者Animal的任意子类。

在这个方法的返回值中,约定了List中可以存储存储任意Animal类型的对象。由于Java支持多态的特性,所以此处可以是Animal或者Animal的任意子类。

此时就会发现一个问题,假如在参数列表中存储的对象是Dog类型,那么返回时的泛型就应该是Dog而不是Animal,这就像之前多态时学习的:

Animal a = new Dog();
Dog d = a;

第二行代码显然是有错的,因为不能将父类型对象直接存储在子类型引用中,即使类型是匹配的。此处必须使用强制类型转换来完成。

在集合中也是一样的,如果尝试将一个元素都是父类型的集合,转换为一个元素都是子类型的集合,可能会出问题。所以实际上,在集合中,泛型是不支持多态的写法的。例如不能写

ArrayList<Animal> list = new ArrayList<Dog>();

所以,方法animalGame在被调用之后,由于其返回值是List<? extends Animal>的,那么接收的数据类型必须也是List<? extends Animal>,不能写为List<Animal>。

祝学习愉快~


  • 提问者 鱿鱼三明治 #1

    了解了   那这段练习是这样做的吗?  还有什么不对的吗?

    2024-05-22 14:57:35
  • 好帮手慕小蓝 回复 提问者 鱿鱼三明治 #2

    同学你好,将animalGame方法返回值的泛型设置为Animal就可以了。其他位置都是正确的。

    祝学习愉快~

    2024-05-22 15:03:52
  • 提问者 鱿鱼三明治 #3

    还有就是用list通配符接收之后   这个对象也只是list对象  存储的也是引用  for循环调用之后为什么就可以了呢   for(Animal a:list)  我可以理解为创建了一个animal对象a   把list的值轮流赋值给a吗?  而后这个引用才生效  才可以调用animal及其子类的属性和方法?

    2024-05-22 15:06:29
问题已解决,确定采纳
还有疑问,暂不采纳

恭喜解决一个难题,获得1积分~

来为老师/同学的回答评分吧

0 星
Java工程师 2024版
  • 参与学习       2025    人
  • 提交作业       1318    份
  • 解答问题       1228    个

2024重磅革新,超百小时内容豪华升级,加速提升高级技能与高薪就业竞争力 课程紧贴企业最新人才需求,历经7年持续迭代,帮助万名学子入行转行 从零起点到高阶实战,学习路径稳健顺滑,成就从小白到工程师高薪

了解课程
请稍等 ...
意见反馈 帮助中心 APP下载
官方微信

在线咨询

领取优惠

免费试听

领取大纲

扫描二维码,添加
你的专属老师