【问题标题】:Java Generics - Method overridingJava 泛型 - 方法覆盖
【发布时间】:2015-03-27 18:28:57
【问题描述】:

我有一对 ClassA 和 ClassB 如下所示。
案例一:

class ClassA<T extends Number>{
    void method(T t){}
}

class ClassB extends ClassA<Integer>{
    @Override
    void method(Integer i){}
}

案例2:

class ClassA{
    void method(Number t){}
}

class ClassB extends ClassA{
    @Override
    void method(Integer i){}
}

我有两个问题。
[q1] 我这样说对吗,case2 是 case1 的运行时表示(类型擦除后)?

[q2] 如果我对 [q1] 的看法是正确的,那么为什么 case1 被接受为有效的覆盖? (我知道为什么 case2 不是有效的覆盖,因为参数不一样。)

请有人对此有所了解。 提前致谢。

【问题讨论】:

  • case 1 中,指定TInteger,因此用T = Integer 覆盖是有效的。但是Number 不是Integer,如果它是&lt;? extends Number&gt; 就可以了。或者至少这可能有效,我需要检查一下。

标签: java generics


【解决方案1】:

[q1] 的答案是否定的。 编译器将在ClassB 中生成一个bridge 方法,该方法实际上将覆盖method(Number)

class ClassB extends ClassA{
    // bridge method
    void method(Number i){
        method((Integer)i);
    }

    void method(Integer i){}
}

您将在类型擦除的java doc 中获得完整的答案。

【讨论】:

    【解决方案2】:

    在 Java(自版本 5 起)中,被覆盖方法的返回类型必须是协变的,而被覆盖方法的参数必须是逆变的。

    这意味着覆盖类可以更具体地返回什么,并更接受它接收的内容。

    在您的第二个示例中,想象一个 ClassA 类型的变量,并以 ClassB 的实例作为值。

     ClassA a = new ClassB(); // This is legal, since ClassB is a subclass of ClassA
     a.method(1.0); // This is legal, since ClassA.method accepts Number
    

    但是,其他方式也可以:

    public class ClassC { public Number method(Integer i) {...} }
    public class ClassD extends ClassC {
       @Override 
       public Integer method(Number n) {...}
    }
    

    是有效的,因为ClassD 仍然履行ClassC 定义的合同。

    【讨论】:

    • -1,对不起。这是错误的:被覆盖方法的参数类型必须完全匹配。逆变是不够的。您的示例代码将无法编译。
    • ClassA a = new ClassB(); a.method(1.0); 仅适用于原始类型。 (它会抛出一个ClassCastException。)此外,Java 中的方法覆盖不允许允许逆变参数。
    • 你是对的。必须为逆变参数创建一个桥接方法。
    【解决方案3】:

    ClassB 的实际超类是ClassA&lt;Integer&gt;。因此其成员函数method 具有编译时签名:

    void method(Integer t){}
    

    你可以通过调用类似的东西来说服自己

    ClassA a = new ClassB();
    a.method(1.0);
    

    您应该会看到运行时错误。实际上只能编译这个,因为我使用了ClassA的擦除版本。事实上,每一个任务 ClassA&lt;Integer&gt; 以外的泛型类型(例如 ClassA&lt;Number>)会因类型不兼容而失败。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-07-01
      • 2014-05-23
      相关资源
      最近更新 更多