【问题标题】:Java generic method overridingJava 泛型方法覆盖
【发布时间】:2014-06-04 09:48:42
【问题描述】:
abstract class A {
    abstract public void dosome(Class<? extends Number> c);
}

class B extends A {
    @Override
    public void dosome(Class<Number> c) {}
}

来自 Java 文档: 在类 C 中声明的实例方法 m1 覆盖在类 A 中声明的另一个实例方法 m2,前提是满足以下所有条件: ...... m1 的签名是 m2 签名的子签名(第 8.4.2 节)。

如果满足以下任一条件,方法 m1 的签名是方法 m2 签名的子签名: m1 的签名与 m2 签名的擦除(第 4.6 节)相同。

是A的擦除

dosome(Class<Number> c)?

如果是这样,有什么问题?

EDIT1: 或者如果我切换泛型类型:

abstract class A {
    abstract public void dosome(Class<Number> c);
}

class B extends A {
    @Override
    public void dosome(Class<? extends Number> c) {}
}

在这种情况下有什么问题?

EDIT2:我知道如何修复它,但我想了解,根据 java 规则,在这种情况下有什么问题。

【问题讨论】:

    标签: java generics overriding


    【解决方案1】:

    如果您希望能够根据每个参数类型必须扩展的公共基类型在子类中定义具体的参数类型,则必须编写类似

    abstract class A<T extends Number> {
        abstract public void dosome(Class<T> c);
    }
    
    class B extends A<Number> {
        @Override
        public void dosome(Class<Number> c) {}
    }
    

    您的代码的问题是? extends Number 的特殊含义描述了具有给定“上限”的“未知”类型,当您不关心或无法获得具体类型时可以使用它.

    【讨论】:

    • A dosome(Class c) 的擦除吗?
    • 在我的代码中?不,擦除取决于具体的子类。
    • “擦除取决于具体的子类”是什么意思。如果不创建子类,擦除就不存在?
    • 如果不创建抽象类的子类,这些类的对象将不存在。正如我所写,A 意味着具体的擦除取决于定义 T 的子类。
    【解决方案2】:

    abstract 类中的方法dosome,调用者可以选择调用任何类型的class,只要它是某种类型的Number

    abstract public void dosome(Class<? extends Number> c);
    

    但是你重写了类似的方法

    public void dosome(Class<Number> c) {}
    

    这将阻止用户调用任何类型的Number,这意味着您不能使用integer 类型调用。

    根据覆盖规则,您不能更改method 参数。 所以,

    Class&lt;? extends Number&gt;Class&lt;Number&gt; 不一样,它是两种不同类型的参数,这就是编译器错误的原因。

    【讨论】:

    • 好的,如果我像这样切换 "? extends Number" 有什么问题: abstract public void dosome(Class c); public void dosome(Class extends Number> c)
    • 您的意思是更严格:参数、返回类型或访问级别?
    猜你喜欢
    • 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
    相关资源
    最近更新 更多