【问题标题】:Java, Generics and inheritance [duplicate]Java,泛型和继承[重复]
【发布时间】:2014-07-31 15:36:23
【问题描述】:

我有一个关于泛型、继承和接口的基本问题。

给定以下代码:

import java.util.ArrayList;
import java.util.List;

public class Generics {

    private Class1 obj1 = new Class1();

    public Generics() {
        Class1 obj1 = new Class1();
        Class2 obj2 = new Class2();
        Class2 obj3 = new Class2();
        Class2 obj4 = new Class2();

        List<Class2> obj1Children = new ArrayList<Class2>();

        obj1Children.add(obj2);
        obj1Children.add(obj3);
        obj1Children.add(obj4);
    }

    public static void main(String[] args) {
        Generics g = new Generics();
    }


    private class Class1 implements I1 {

        private List<I2> children;

        @Override
        public List<I2> getChildren() {
            return children;
        }

        @Override
        public void setChildre(List<I2> children) {
            this.children = children;
        }
    }

    private class Class2 implements I2 {
    }

    private interface I1 {
        List<I2> getChildren();
        void setChildre(List<I2> children);
    }

    private interface I2 {
    }
}

在 Class1 中,如果您更改线路:

    private List<I2> children;

    private List<Class2> children;

然后我有一个编译错误告诉我它不能将 List 转换为 List。

我很困惑,因为我认为接口的全部意义在于摆脱事物的实现方面。

谁能解释一下?

【问题讨论】:

标签: java generics inheritance interface


【解决方案1】:

I1 明确定义了一个返回List&lt;I2&gt; 类型的方法。您不能在实现类中出于任何原因更改它以返回 List&lt;Class2&gt;;这就是界面的全部意义所在。您实施I1 的合同强制您在任何情况下都返回List&lt;I2&gt; 类型。

除了接口实现对你的限制之外,你还应该知道“泛型”是不宽容的; I2 中的 List&lt;I2&gt; 不能转换为其他任何东西。甚至不是同一层次结构中的一个类。 java提供的类型安全在这方面是相当严格的

考虑一下:

  1. Class2 is-a I2
  2. List&lt;Class2&gt; 定义了一个类型安全的 Class2s 集合
  3. List&lt;I2&gt; 定义了一个类型安全的 I2s 集合
  4. Java 在任何时候都不允许List&lt;Class2&gt; 被替换为List&lt;I2&gt;。不在变量声明、方法参数或方法返回值中

【讨论】:

  • 这是答案的一半。另一半依赖于泛型不会相互扩展的事实。 List&lt;Class2&gt; 不扩展 List&lt;I2&gt;
  • 正在回答@LuiggiMendoza :)
  • 好吧,即使我冒着被一个完整的菜鸟传球的风险,我也不明白你在评论@LuiggiMendoza。我知道List&lt;Class2&gt; 不扩展List&lt;I2&gt; 但另一方面Class2 实现I2 意味着处理I2 的任何相关信息也存在于Class2 上,因此允许使用Class2 实例指定了I2 的任何位置。还是我们不是在谈论流程中的同一步骤(编译时间为你,运行时间为我)?
  • @Marco 我的评论意味着List&lt;Class2&gt; 没有通过List&lt;I2&gt; 的IS-A 测试。如果您声明返回List&lt;I2&gt;,则不能返回List&lt;Class2&gt;。但是如果你声明你返回一个I2,你可以返回一个Class2
  • @Marco - 请允许我在答案中澄清(我显然做得不够好)
【解决方案2】:

在您提到的代码中,返回类型是&lt;I2&gt;。但是如果你想要你的方法会得到 任何数据类型作为参数,而不是使用 Object Simple 之一。

【讨论】:

    【解决方案3】:

    这不是 Class1.setChildren() 实现中的问题:它接受 I2 的任何实现,但您的内部 List 只接受 Class2 实现。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-08-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-03-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多