当前位置: 首页 > 知识库问答 >
问题:

泛型方法(有界类型)vs继承

秦安宁
2023-03-14

我有一个典型的问题,什么是更好的,我认为答案总是视情况而定,但我还是想澄清一下。所以有两种方法:

java prettyprint-override">public static <A extends Animal, F extends Food> void feed(A animal, F food) {
    animal.setFood(food);
}

public static void feed(Animal animal, Food food) {
    animal.setFood(food);
}

逻辑是:

Cat cat = new Cat(); // Cat is a child of Animal
Dog dog = new Dog(); // Dog is a child of Animal

Pork pork = new Pork(); // Pork is a child of Food
pork.setName("Whiskas");
Beef beef = new Beef(); // Beef is a child of Food
beef.setName("Pedigree");

AnimalService.feed(cat, beef);
AnimalService.feed(dog, pork);

cat.eat(); // prints I'm eating Pedigree
dog.eat(); // prints I'm eating Whiskas

我知道由于类型擦除,方法签名存在冲突,所以我的问题不是“为什么我不能同时拥有这两个方法?”,而是“你会选择哪种方法?”。

共有1个答案

梅修贤
2023-03-14

就像你说的,看情况。您需要记住,泛型是一个编译时工具,可以帮助编译器进行一些检查,并在您违反约束时吐出错误。

在您的例子中,除了参数类型的上限(AnimalFood)之外,您似乎没有任何要违反的约束,因此您不会从使用泛型中获得任何好处-因此我选择基于简单继承的方法。

然而,考虑你正在改变你的<代码>动物< /代码>界面,以定义动物需要的食物种类(从而增加了一个约束,即继承不能帮助你在编译时执行):

interface Animal<F extends Food> { ... }

class DogFood implements Food { ... }
class CatFood implements Food { ... }
class Whiskas extends CatFood { ... }

class Dog implements Animal<DogFood> { ... }
class Cat implements Animal<CatFood> { ... }

现在feed()可以使用泛型来让编译器帮助您选择正确的食物类型:

<F extends Food> void feed(Animal<F> animal, F food) { ... }

//this should compile because Cat defines Food needs to be CatFood
feed(new Cat(), new CatFood());

//this should also compile because Whiskas is CatFood
feed(new Cat(), new Whiskas());

//this shouldn't compile because DogFood is not CatFood
feed(new Cat(), new DogFood());
 类似资料:
  • 我有一个典型的问题,什么是更好的,我认为答案总是视情况而定,但我还是想澄清一下。所以有两种方法: 逻辑是: 我知道由于类型擦除,方法签名存在冲突,所以我的问题不是“为什么我不能同时拥有这两个方法?”,而是“你会选择哪种方法?”。

  • 在了解Java泛型的过程中,我遇到了以下问题: 假设我有下面的方法来添加列表的元素,只限于包含数字的列表。 但是这段代码和这段代码有什么不同: 它们都按预期编译和执行。这两者之间有什么区别?除了语法之外?什么时候我更喜欢使用通配符而不是前者? 是的,使用通配符方法,我不能在列表中添加除null之外的新元素,否则它将无法编译。除此之外呢?

  • 问题内容: 以下两个签名是否相同? 和 问题答案: 不,两个签名不相同。根据Java语言规范的第8章: 如果两个方法具有相同的名称和参数类型,则它们具有相同的签名。 如果满足以下所有条件,则两个方法或构造函数声明M和N具有相同的参数类型: 它们具有相同数量的形式参数(可能为零) 它们具有相同数量的类型参数 (可能为零) … 由于两种方法共享的类型参数数量不同,因此签名也不相同。 在实际情况下,使用

  • 问题内容: 如果在Java中创建泛型类(该类具有泛型类型参数),则可以使用泛型方法(该方法带有泛型类型参数)吗? 考虑以下示例: 正如您对通用方法所期望的那样,我可以使用任何对象调用的实例: 但是,如果我尝试使用 不 指定泛型类型的实例,则无论传入什么,我都会调用返回, 奇怪的是,如果返回类型是通用类,它将编译(例如(实际上,这可以解释-参见下面的答案)): 此外,如果输入通用类,即使仅使用通配符

  • 如果在Java中创建泛型类(该类具有泛型类型参数),是否可以使用泛型方法(该方法采用泛型类型参数)? 考虑下面的例子: 正如您所期望的那样,对于任何对象,的实例,我都可以调用: 但是,如果我试图使用的实例而不指定泛型类型,那么调用将返回一个

  • 我读了很多文章,但我不明白这两行之间的区别: 我看到的唯一区别是第一行触发了“未检查的分配”警告。