使用<! - ?有什么区别?在Java泛型中扩展了SomeAbstract - >与SomeAbstract的对比

时间:2011-06-15 16:34:15

标签: java generics programming-languages abstract extends

我正在从DotNet转向java,这种扩展的想法是新的。

我看到一些帖子完全解释了使用List<? extends SomeAbstract>List<? super SomeAbstract>List<SomeAbstract>的对比,但我猜测使用和不使用之间没有区别延伸到泛型。

这是真的吗?如果使用抽象类作为父类,答案会改变吗?

class My_AbstractExtends<T extends SomeAbstract>

VS

class My_Abstract<SomeAbstract>

修改

按如下方式创建子类

class My_ChildExtends extends My_AbstractExtends<ConcreteChildOfSomeAbstract>

VS

class My_Child extends My_Abstract<ConcreteChildOfSomeAbstract>

3 个答案:

答案 0 :(得分:8)

我猜你在谈论在类型参数声明中使用extends。在那种情况下:

class My_Abstract<T extends SomeAbstract>

有一个名为T的有界类型参数,必须是SomeAbstract或其某个子类型。

class My_Abstract<SomeAbstract>

有一个名为SomeAbstract的无界类型参数,可以是任何东西。请注意,SomeAbstract不再引用第一个示例使用的实际类型SomeAbstract

要进一步扩展:假设第二个声明是class My_Abstract<T>T显然有一个类型参数,而不是实际类型。但它不必被称为T ......它可以被称为EBobSomeAbstract。在所有这些情况下,它仍然只是一个类型参数...实际类型永远不会去那里,它也没有任何意义(类型参数的整个点是不引用特定类型,但而是在创建类的实例时允许其他类型放在其位置。)

在您编辑的代码中,将My_Child的声明更改为

class My_Child extends My_Abstract<Object>

你会看到差异。如果你真的试图在第二个版本中使用类型参数SomeAbstract做某事,你也会发现你不能调用真实SomeAbstract类中声明的任何方法。这就是为什么你应该总是遵循使用单字母类型参数的惯例的一个很好的例子......如果你不这样做,那真是令人困惑。

这已经很长了,但我还要注意,所有这一切基本上与你问题的前半部分无关。像? extends SomeAbstract? super SomeAbstract这样的通配符不用于类型参数声明(例如定义泛型类时使用的那些),它们主要用于方法参数。 List是解释为什么需要通配符的典型示例,因为它作为对象容器的性质使其相对容易理解,但与它们相关的规则适用于任何泛型类型。我试图在this answer中以相对笼统的术语解释这一点。

答案 1 :(得分:2)

它可以让您在其他地方引用T

public class A<T extends SomeClass>{
    public A(T x){this.x=x;}
    public T x;
}

然后,您班级的用户可以使用原始类型,而不必使用SomeClass。

MyObject x = new A<MyObject>(new MyObject()).x;

答案 2 :(得分:0)

在泛型类声明中使用extends

  1. 将可用作参数的类型限制为从扩展类下降的类型。
  2. 允许泛型类调用扩展类中声明的方法。
  3. '?'当手头的代码不关心类型参数的特定类型时,关键字用在方法中,但只关心它上面的低(扩展)或上(超)绑定。

    维基百科explains以非常实用的方式对不同结构的净效应。

    要理解为什么需要几种不同的结构来指定泛型,你必须阅读covariance and contravariance,它们是存在泛型的静态类型安全规则的理论名称。