为什么A-> B不会使List – > List ? 这不会消除对通配符的需求吗?

免责声明:我不是专业开发人员,我不打算成为一名开发人员。 关于Java的阅读书,因为我想尝试Android编程,没有任何以前的Java经验。

我正在读这本书 – 我更喜欢它。 我已经阅读了关于generics类的章节的一部分,到了他们提到通配符的地步,并且感到困惑。

如果B延伸A:

  1. List 不是 List的子类型(据我所知,它们完全相同)
  2. List ListList的子类型List List

后者允许编写接受generics类型参数的函数 – 例如List List 。 这样的函数会接受ListList

现在,对于我的问题:

以类似于C ++(以“模板”风格)的方式实现generics不是更简单吗? 这将使ListList两种不同的类型,这些类型将以预期的方式相关。 这也可以简单地在函数中声明你期望参数是List类型,这将允许List适合那里。

我猜测不仅仅是“我们讨厌C ++,让我们做出与众不同”这一点:)我很可能还不知道什么,这使得通配符成为一个非常有用的工具。 你对此有何看法?

编辑:如果您在答案中提到List ,请记住使用反引号,以避免被解释为HTML标记。

原因很简单。

假设您有一个List类型的变量。 假设List确实是List的子类型。

这意味着当这是合法的:

 List a_list; a_list = new List(); //allowed when List is subtype of list a_list.add(new A()); // WOAH! 

在我说WOAH时,会发生以下情况:您向a_list添加A类型的项目。 由于a_list被声明为List ,这应该是合法的。 但是等一下:a_list指向List类型的东西。

所以现在我们将一个类型A的东西添加到一个列表中,该列表应该只存储B类的项目,这显然不是我们想要的,因为A不是B的子类!

问题是,如果你有class C extends A并给出List ,你可以放入一个C ,因为CA 但是如果Java允许你只给方法一个List ,那么你就把C放在一个B列表中。 并且C不是B ,因此会出现错误。 Java的通配符解决方案不允许您向List添加任何null List List ,从而避免这个错误。

好吧, Comeau c ++在线编译器失败了:

 template class List { }; class A { }; class B: public A { }; void function(List listA) { } int main(int argc, char** argv) { List a; List b; function(a); function(b); } 

给出这个错误:

 "ComeauTest.c", line 18: error: no suitable user-defined conversion from "List" to "List" exists function(b); 

因此,在处理这些类型时,C ++和Java是相似的。

静态类型表明子类型必须支持其超类型的所有操作。

List支持插入Fruit对象。

List没有 – 您不能将任意水果插入List ,只能插入香蕉。

因此, List不是List的子类型。