Interface-Class允许静态成员方法到实例成员方法重新声明,但Class-Class或Interface-Interface不允许
Static member method to Instance member method redeclaration allowed for Interface-Class but not for Class-Class or Interface-Interface
考虑以下片段:
interface Super{
public static void doIt(){}
}
class Sub implements Super{
public void doIt(){}
}
- 在这里我已经声明了一个静态成员方法,它正在被重新声明为子方法中的实例方法class。
- 这是编译器允许的 - 但是当我对 superclass 和 subclass 类型做同样的事情时 - 这会产生编译错误:
class Super{
public static void doIt(){}
}
class Sub extends Super{
public void doIt(){}
}
- 相同背后的基本原理是什么? - 理想情况下访问子class 的方式基本相同 - 那么为什么要有这个限制?
原因是 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();
}
}
出于同样的原因,不可能在父 class 中使用 static test()
方法 - 同样的规则适用。在 Java 中调用超级 class 的 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
方法(编辑:因为它们不是被继承)。以下将 not 工作(方法 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
class中定义方法的区别:调用方式。如果您实现多个接口,这些接口都具有具有相同签名的 static
方法,编译器将无法知道调用哪一个。
这就是为什么允许在实现的接口中定义具有相同签名的 static
方法,但不能在父 classes 中定义方法的原因。
考虑以下片段:
interface Super{
public static void doIt(){}
}
class Sub implements Super{
public void doIt(){}
}
- 在这里我已经声明了一个静态成员方法,它正在被重新声明为子方法中的实例方法class。
- 这是编译器允许的 - 但是当我对 superclass 和 subclass 类型做同样的事情时 - 这会产生编译错误:
class Super{
public static void doIt(){}
}
class Sub extends Super{
public void doIt(){}
}
- 相同背后的基本原理是什么? - 理想情况下访问子class 的方式基本相同 - 那么为什么要有这个限制?
原因是 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();
}
}
出于同样的原因,不可能在父 class 中使用 static test()
方法 - 同样的规则适用。在 Java 中调用超级 class 的 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
方法(编辑:因为它们不是被继承)。以下将 not 工作(方法 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
class中定义方法的区别:调用方式。如果您实现多个接口,这些接口都具有具有相同签名的 static
方法,编译器将无法知道调用哪一个。
这就是为什么允许在实现的接口中定义具有相同签名的 static
方法,但不能在父 classes 中定义方法的原因。