最终归结为这样一个事实,当你有像这样的东西:
class Me {
public static void go() {
System.out.println("going");
}
}
以下两种都是允许的:
Me.go();
Me meAgain = new Me();
meAgain.go(); // with a warning here
有趣的是,这个例子也可以工作:
Me meAgain = null
meAgain.go()
我个人认为这是一个设计缺陷,由于兼容性无法撤回 - 但我希望编译器不允许我从实例访问静态方法。
你的第一个问题与java-8本身无关,在java-8之前就是这样的:
interface ITest {
public void go();
}
class Test implements ITest {
public static void go() {
}
}
默认方法在这里也遵循相同的规则。为什么会这样发生,实际上在stackoverflow上已经详细解释了很多 - 但其基本思想是潜在地会导致调用哪个方法的混淆(想象一下ITest将是Test扩展的类,并且您执行ITest test = new Test(); test.go(); -> 您正在调用哪个方法?)
我认为出于同样的原因,这也是不允许的(否则您将具有相同签名的静态和非静态方法)。
static class Me {
static void go() {
}
void go() {
}
}
有趣的是,在方法引用中这种问题已经得到了解决(我猜他们意识到再犯同样的错误会很糟糕):
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);
IntStream.of(1, 2, 3).map(m::decrement);