首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >泛型:为什么用“B<Superclass>类”代替“A类<E扩展Superclass>”?

泛型:为什么用“B<Superclass>类”代替“A类<E扩展Superclass>”?
EN

Stack Overflow用户
提问于 2016-03-14 01:23:26
回答 2查看 535关注 0票数 13

我正在试验Java泛型。据我所知,使用Java泛型,我们可以创建只处理特定类型的类和方法。这使得能够在编译时检测编程错误。

我的问题可能听起来很奇怪。为什么不使用Superclass而使用E extends Superclass?请看一下下面的代码。

代码语言:javascript
复制
class Hunter <E extends Animal>{}

class Keaper <Animal>{}
    /*edit: as AR.3 and other pointed out, Keaper<Animal> is the same as Keaper<E>.
 Animal  is just a type parameter here*/

class Animal{}

class Cat extends Animal{}

class Dog extends Animal{}


public class TestGeneric {
    public static void main(String[] args) {
        Hunter<Cat> hunter1 = new Hunter<>();
        Hunter<Dog> hunter2 = new Hunter<>();
        Hunter<Animal> hunter3 = new Hunter<>();

        ArrayList<Hunter> hunters=  new ArrayList<>();
        hunters.add(hunter1);
        hunters.add(hunter2);
        hunters.add(hunter3);

        Keaper<Cat> keaper1 = new Keaper<>();
        Keaper<Dog> keaper2 = new Keaper<>();
        Keaper<Animal> keaper3 = new Keaper<>();
//Edit: as AR.3 and others pointed out, Keaper<String> is also legal here.

        ArrayList<Keaper> keapers=  new ArrayList<>();
        keapers.add(keaper1);
        keapers.add(keaper2);
        keapers.add(keaper3);
    }
}

我觉得E extends AnimalAnimal几乎是一样的,只是前者提供了更多的信息。有什么想法吗?

EN

回答 2

Stack Overflow用户

发布于 2016-03-14 01:27:41

实际上,在Keaper类的定义中声明的Animal只是一个类型参数(更传统的做法是只使用一个字母,如Keaper<T>)。因此,这是一个完全不同的类型参数范围:Keaper类可以接受任何类型作为参数,而不仅仅是Animal。您可以编写Keaper<String>,它可以很好地编译,这显然不是您想要的。

使用泛型是不可能实现的:您不能强制一个类成为泛型,并且只与一个可能的类型参数相关联。您可以做的是将关联类型的范围限制为,例如,扩展特定类型的任何类型,您已经对Hunter类执行了此操作。

此外,正如@JHH的注释中所提到的,您应该避免在列表中使用Keaper作为原始类型,否则代码将不是完全泛型的。您可以编写ArrayList<Keaper<? extends Animal>> keapers = new ArrayList<>()而不是ArrayList<Keaper> keapers = new ArrayList<>()

票数 15
EN

Stack Overflow用户

发布于 2016-03-14 01:34:38

通常,当您想要保留特定类型的in参数时,可以使用extends。考虑这个例子:

代码语言:javascript
复制
public class TestGeneric {

    public static <T extends Animal> T changeExtendedAnimal(T extendedAnimal) {
        return extendedAnimal;
    }

    public static Animal changeAnimal(Animal animal) {
        return animal;
    }

    public static void main(final String[] args) {
        Cat changedCat1 = changeExtendedAnimal(new Cat()); //Compiles fine. 
        Cat changedCat2 = changeAnimal(new Cat()); //Won't compile: Type mismatch: cannot convert from Animal to Cat
    }
}

这里的changeExtendedAnimal()方法使用了扩展,因此,如果您使用Cat调用该方法,编译器就会知道您将得到一个Cat

另一方面,使用changeAnimal()方法,编译器无法知道这一点,因此会得到一个编译时错误。

票数 10
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/35973304

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档