use*_*089 12 java inheritance multiple-inheritance default-method
我有以下情况:
class C {
static void m1() {}
}
interface I {
default void m1() {}
}
//this will give compilation error : inherited method from C cannot hide public abstract method in I
class Main extends C implements I {
}
Run Code Online (Sandbox Code Playgroud)
以下是我的问题:
我知道实例方法将覆盖默认方法,但是如果类中的静态方法与Interface中的默认方法具有相同的签名呢?
如果静态方法m1()在class C将公共那么编译错误将是:
静态方法m1()与I.中的抽象方法冲突
因此,当访问修饰符是默认值时,它试图隐藏,当它是公共时,它是冲突的.为什么会有这种差异?它背后的概念是什么?
最终归结为这样一个事实:当你有这样的事情时:
class Me {
public static void go() {
System.out.println("going");
}
}
Run Code Online (Sandbox Code Playgroud)
这两者都是允许的:
Me.go();
Me meAgain = new Me();
meAgain.go(); // with a warning here
Run Code Online (Sandbox Code Playgroud)
有趣的是,这也可以工作,例如:
Me meAgain = null;
meAgain.go();
Run Code Online (Sandbox Code Playgroud)
就我个人而言,我仍然认为这是由于兼容性而无法撤销的设计缺陷 - 但我希望编译器不允许我从实例访问静态方法。
你的第一个问题与java-8本身无关,在java-8之前它是这样的:
interface ITest {
public void go();
}
class Test implements ITest {
public static void go() { // fails to compile
}
}
Run Code Online (Sandbox Code Playgroud)
默认方法在这里遵循相同的规则。为什么会发生这种情况实际上在堆栈溢出上有很多详细说明 - 但潜在的想法是,这可能会导致调用哪个方法的混乱(想象一下,ITest将是一个Test会扩展的类,而您会这样做ITest test = new Test(); test.go(); -> 您正在调用哪个方法? )
我认为出于同样的原因,这也是不允许的(这基本上是你的第二个问题,否则你将拥有具有相同签名的静态和非静态方法)
static class Me {
static void go() {
}
void go() {
}
}
Run Code Online (Sandbox Code Playgroud)
有趣的是,这在方法引用中是固定的(我猜他们意识到再次犯同样的错误真的很糟糕):
static class Mapper {
static int increment(int x) {
return x + 1;
}
int decrement(int x) {
return x - 1;
}
}
Mapper m = new Mapper();
IntStream.of(1, 2, 3).map(m::increment); // will not compile
IntStream.of(1, 2, 3).map(m::decrement); // will compile
Run Code Online (Sandbox Code Playgroud)
因为java中的类方法也可以使用实例变量来调用,所以这种构造会导致歧义:
Main m = new Main();
m.m1();
Run Code Online (Sandbox Code Playgroud)
目前还不清楚最后一条语句应该调用类方法C.m1()还是实例方法I.m1()。
| 归档时间: |
|
| 查看次数: |
625 次 |
| 最近记录: |