4

如果三个公共接口定义为:

public interface One{}
public interface Two{}
public interface Three{}

另一个类 Super 定义为:

public class Super {
    public static <E extends One & Two & Three> void hmm(E item) {}
}

为什么 Super 的以下子类会出现编译错误?

public class Subber extends Super{
    public static void hmm(One item) {}
}

我希望上述方法可以简单地隐藏 Super 的方法,但事实并非如此。

JLS (8.4.8.2) 说:

如果类 C 声明或继承静态方法 m,则称 m 隐藏任何方法 m',其中 m 的签名是 m' 签名的子签名(第 8.4.2 节),位于否则可以访问(第 6.6 节)以用 C 编写代码的 C。

其中子签名在 8.4.2 中定义为:

如果两个方法或构造函数 M 和 N 具有相同的名称、相同的类型参数(如果有)(第 8.4.4 节),并且在将 N 的形式参数类型调整为类型参数之后,则它们具有相同的签名的 M,形参类型相同。

方法 m1 的签名是方法 m2 的签名的子签名,如果: m2 与 m1 具有相同的签名,或者 m1 的签名与 m2 签名的擦除(第 4.6 节)相同。

根据 JLS 4.6,类型变量的擦除是其最左边界的擦除,因此:据我了解,Subber 的 hmm 方法与 Super 的 hmm 方法的擦除相同,因此是 Super 的 hmm 的子签名,因此意味着它会隐藏 Super 的嗯。但是,我得到的错误消息(来自 eclipse),鉴于上述情况,这似乎没有意义:“Subber 类型的方法 hmm(One) 与 Super 类型的 hmm(E) 具有相同的擦除,但没有把它藏起来。” 我错过了什么?

编辑:主要方法仅包含的精确错误消息Subber.hmm(null);是:

Exception in thread "main" java.lang.Error: Unresolved compilation problem: 
    Name clash: The method hmm(One) of type Subber has the same erasure as hmm(E) of type Super but does not hide it

    at base/testpack4.Subber.hmm(Subber.java:4)
    at base/testpack4.Main.main(Main.java:5)

有人可以引用可靠的来源(最好是 JLS)解释为什么 Subber 的方法无法编译吗?

4

2 回答 2

2

„<em>...有人能解释一下为什么 Subber 的方法无法编译...“</p>

实现了您列出的代码逐字逐句。我Main.main(String[])通过调用Subber.hmm(null)and编译得很好Subber.hmm(One)

唯一不同的是我引入了一个新的Four接口来满足<E extends One & Two & Three> void Super.hmm(E).

Four然后我传递了一个into的实例Subber.hmm(One)来确认它Super.hmm(E)没有被调用;证明它实际上是隐藏的。

„<em>...引用可靠来源(最好是 JLS)?...“</p>

该实现的行为与您引用的 JLS 规范完全相同。

于 2020-07-02T07:33:47.383 回答
-2

E 的类型仍然未定义,您可以通过设置 Super 类的 E 泛型并在 Subber 类中定义它来参数化它:

public class Super<E> {
    public static <E extends One & Two & Three> void hmm(E item) {}
}

public class Subber extends Super<One> {
    public static void hmm(One item) {}
}
于 2020-06-30T20:15:47.423 回答