Java Iterator <e>,类型E的继承</e>

时间:2014-11-12 13:55:32

标签: java inheritance iterator

我发现了一些对我很有趣的东西。请考虑以下代码:

// file: example.java
interface Interface1
{
    Iterator<Interface2> getIterator();
}

interface Interface2
{
}

interface Interface3 extends Interface2
{
}

class Class1 implements Interface1
{
    Iterator<Interface3> getIterator(); // Compiler throws error: type mismatch
}

我的问题是:

  1. 这种行为是否记录在某处?
  2. 这种行为是正确的吗?

3 个答案:

答案 0 :(得分:4)

是的,这是在某处记录的,即the Java Tutorial about generics。它也是有目的的。

如果BA的子类型,那么SomeClass<B>不是SomeClass<A>的子类型。原因如下。假设以下代码将编译:

public static void main(String[] args)
{
    ArrayList<B> list = new ArrayList<>();

    // if ArrayList<B> would be a subtype of ArrayList<A> 
    // this would be legal:
    ArrayList<A> list2 = list; 

    A element = new A();
    list2.add(element);
    // Uh-oh. Now list contains non-B elements.

    B b = list.get(0); // <--- ClassCastException
}

然后可以绕过type参数并将非B对象添加到B列表中。为了解决这个问题,Java提供了绑定类型变量:类型变量可以通过extendssuper关键字在上下绑定。有关如何使用它们的信息,请参阅Java Turorial。

答案 1 :(得分:2)

首先要实现和接口你必须使用implements not extends。其次,当使用泛型时,您可以使用扩展。 在界面中,您已经定义了一个方法,可以为您提供Iterator<Interface2> getIterator();,但在您正在执行的实现中Iterator<Interface3> getIterator();

哪些不起作用你可以做的是使用这样的泛型(已验证不会给出编译错误):

interface Interface1
{
    Iterator<? extends Interface2> getIterator();
}

interface Interface2
{
}

interface Interface3 extends Interface2
{
}

class Class1 implements Interface1
{
    public Iterator<Interface3> getIterator(){
        return null;
    } 
}

答案 2 :(得分:1)

您已实施Interface1,其getIterator()方法返回Iterator<Interface2>。这意味着您的实现类需要其getIterator()方法来返回Iterator<Interface2>类型的内容;你要归还Iterator<Interface3>类型的东西。

您遇到的根本问题是虽然Interface3扩展了Interface2,但这并不意味着Iterator<Interface3>Iterator<Interface2>的子类型。不幸的是,子类化机制无法“透视”来输入参数。

它有令人讨厌的后果。例如,你不能写

List<List<String>> list = new ArrayList<ArrayList<String>>();

它会给你一个编译器错误,因为右边的表达式与左边的形式类型参数不是赋值兼容的。

虽然ArrayList<String>List<String>的子类型,但ArrayList<ArrayList<String>>不是List<List<String>>的子类型。你有类似的事情发生在这里。