Interface-Class允许静态成员方法到Instance成员方法重新声明,但Class-Class或Interface-Interface不允许[重复]
Posted
技术标签:
【中文标题】Interface-Class允许静态成员方法到Instance成员方法重新声明,但Class-Class或Interface-Interface不允许[重复]【英文标题】:Static member method to Instance member method redeclaration allowed for Interface-Class but not for Class-Class or Interface-Interface [duplicate] 【发布时间】:2021-12-18 12:15:57 【问题描述】:考虑以下 sn-p:
interface Super
public static void doIt()
class Sub implements Super
public void doIt()
这里我声明了一个静态成员方法,它被重新声明为子类中的实例方法。
编译器允许这样做 - 但是当我对超类和子类类型执行相同操作时 - 这会导致编译错误:
class Super
public static void doIt()
class Sub extends Super
public void doIt()
相同的原因是什么? - 理想情况下,访问子类的方式基本相同 - 那么为什么会有这种限制?
【问题讨论】:
我怀疑编译器正在阻止一个错误。因为可以在实例上调用超类上的静态方法(是的,带有警告),这最终可能会产生误导……subObject.doIt()
将调用哪个方法?如果Super
是接口,则不能使用subObject.doIt()
调用Super.doIt()
,编译器已经禁止这样做。
作为类实例一部分的成员被覆盖(即公共和受保护),静态成员不是类实例的一部分,它是实际类的一部分。
【参考方案1】:
这样做的原因是 Java 允许以非静态方式调用 static
方法。考虑这个例子:
public class MyClass
public static void sayHello()
public void test()
this.sayHello();
这将产生编译器警告(MyClass
类型的静态方法 sayHello()
应该以静态方式访问),但它会在运行时正确编译和调用静态方法.
这就是为什么下面的代码由于歧义而无法编译的原因(MyClass 类型中的重复方法test()
):
public class MyClass
public static void test()
public void test()
编译错误的原因是,如果你写如下,编译器无法知道调用哪个方法,因为它允许以非静态方式调用static
方法:
public class MyClass
public static void test()
public void test()
public void execute()
this.test();
出于同样的原因,在父类中不可能有static test()
方法——同样的规则适用。在 Java 中可以调用 static
超类的方法,无论是否有条件:
public class Super
public static void test()
public class Sub extends Super
public void execute()
this.test();
或
public class Sub
public void execute()
test();
this.test()
的调用会产生警告,但会在运行时起作用。
对于接口中的static
方法,上面的示例将不起作用,因为编译器会强制您以限定的方式调用接口的static
方法(编辑:因为它们没有被继承)。以下将不工作(方法 interfaceStatic() 未定义为 Sub 类型):
public interface Interface
public static void interfaceStatic()
public class Sub implements Interface
public void test()
interfaceStatic();
为了调用interfaceStatic()
,调用必须像这样限定:
public class Sub implements Interface
public void test()
Interface.interfaceStatic();
这就是在接口中定义static
方法和在super
类中定义的区别:调用方式。如果你实现了多个接口,这些接口都有一个签名相同的static
方法,编译器就无法知道调用哪一个。
这就是为什么允许在实现的接口中定义具有相同签名的static
方法,但不能在父类中定义的原因。
【讨论】:
一个静态接口方法,当它是作用域时,仍然可以在没有限定符的情况下调用,例如public interface Interface public static void interfaceStatic() default void instanceMethod() interfaceStatic(); /* but not this.interfaceStatic(); */
。同样,当其他类具有适当的import static …;
语句时,它可以将其用作interfaceStatic();
。但是静态接口方法不继承,所以它们不在实现类的范围内,除非它们包含import static …;
语句。由于实现没有继承它,所以没有冲突。
@Holger 是的,这是真的。但这是一个不同的故事,不在问题的范围内。如果通过import static
显式导入,则必须在导入类中自己处理冲突的方法签名。问题是关于“重复定义”错误。如您所知,static
方法属于类,而不是实例。如果 Java 对所有 instance 成员强制使用 this
关键字,则根本没有问题,因为编译器总是知道您指的是什么(类或实例成员)。例如。 TypeScript 允许 OP 的要求。
OP 想知道为什么声明 public void doIt()
在 class Sub implements Super
中被接受,答案是,因为 Sub
没有从 Super
继承 public static void doIt()
方法。如果你试图在Super
中声明该方法,你仍然会得到一个错误,即interface Super public static void doIt() public void doIt();
无法编译,尽管你不能为this.doIt()
接口方法做this.doIt()
。是否能区分调用无关紧要。
你倒退了。该方法未被继承的事实是所有其他事情的原因,而不仅仅是它们所暗示的,因此是为什么问题的答案。
问题不是“为什么 Java 不允许这样做”,而是“为什么在类实现接口的情况下这个声明是可能的 ”,而答案正是“因为在这种情况下,该类没有继承矛盾的方法”。您正在尝试回答一个尚未被问到的问题。以上是关于Interface-Class允许静态成员方法到Instance成员方法重新声明,但Class-Class或Interface-Interface不允许[重复]的主要内容,如果未能解决你的问题,请参考以下文章