我无法理解为什么编译器在编译此代码时会显示错误:
class A
{
public static void f()
{
System.out.println("A.f()");
}
}
class B extends A
{
public static int f()
{
System.out.println("B.f()");
return 0;
}
}
A和B类中两个方法之间的差异是返回类型, 我读到Java防止覆盖静态方法。 所以我期望编译器不应该显示任何错误,因为最初没有任何重写!!
答案 0 :(得分:6)
Java Language Specification具有以下规则:
8.4.8.3。覆盖和隐藏的要求
如果返回类型为R1的方法声明d1覆盖或隐藏了另一个返回类型为R2的方法d2的声明,那么对于d2,d1必须是return-type-substitutable(第8.4.5节),或者是编译时错误发生。
此规则允许协变返回类型 - 在覆盖方法时优化方法的返回类型。
因此,即使该方法隐藏了一个超类并且没有覆盖它,返回类型仍必须兼容。
答案 1 :(得分:2)
正如您所知,类B
中的方法未覆盖类A
中的方法。问题是,对于具有相同签名的类B
,您有两种不同的方法可见。请记住,返回类型不算作方法签名的一部分。
来自JLS §8.4.2 - Method Signature:
如果两个方法具有相同的名称和参数类型,则它们具有相同的签名。
因此,类B
中的方法既不是有效的覆盖,也不是有效的重载。因为重载需要你有不同的方法签名,而你没有。
此外,它既不是隐藏的有效方法,因为它要求您使隐藏方法的返回类型与超类方法的返回类型相同或为子类型。这也没有发生在这里。
因此,要么将类B
方法的返回类型更改为void
,并更改其签名。