Java 为什么我可以从子实例访问我的超类的静态方法?

Java 为什么我可以从子实例访问我的超类的静态方法?,java,static-methods,Java,Static Methods,为什么可以从子实例访问我的超类的静态方法 public class Test { public static void main(String[] args) { new UtilImpl().fun(); new AbstractUtil() {}.fun(); } static abstract class AbstractUtil { public static void fun() { S

为什么可以从子实例访问我的超类的静态方法

public class Test {

    public static void main(String[] args) {
        new UtilImpl().fun();
        new AbstractUtil() {}.fun();
    }

    static abstract class AbstractUtil {
        public static void fun() {
            System.out.println("Fun!");
        }
    }

    static class UtilImpl extends AbstractUtil {
    }

}
我同意从父类的实例访问父类的静态方法。但是如果我实例化一个子类,那么访问父类的静态上下文就很奇怪了

PS


在实例上调用静态方法有什么好处?

它被称为继承。子类继承父类的
public
成员,包括
static
方法。重要的是
静态
方法不绑定到任何实例。你可以这样做:

public class Test {

    public static void main(String[] args) {
        new UtilImpl().fun();
        new AbstractUtil() {}.fun();
    }

    static abstract class AbstractUtil {
        public static void fun() {
            System.out.println("Fun!");
        }
    }

    static class UtilImpl extends AbstractUtil {
    }

}
UtilImpl.fun();
AbstractUtil.fun();

就编译器而言,这是一样的。唯一的区别是代码创建了对象,但这些对象与方法的调用方式无关(正如@Dici在评论中所说的那样,您还应该从编译器那里得到警告)。

在Java中,允许使用实例变量调用静态方法。这在JLS中定义,引用:

声明为静态的方法称为类方法

类方法总是在不引用特定对象的情况下被调用。

在这种情况下,Java实际上会丢弃您使用的实例并调用静态方法

用以下方式表示:

由于 调用模式是静态的,不检查引用以查看 是否为空:

class Test1 {
    static void mountain() {
        System.out.println("Monadnock");
    }
    static Test1 favorite(){
        System.out.print("Mount ");
        return null;
    }
    public static void main(String[] args) {
        favorite().mountain();
    }
}
其中打印:

Mount Monadnock
此处favorite()返回null,但不会引发NullPointerException


为什么?因为它是这样指定的。但是,你会得到一个警告。这个主题已经被很好地介绍过了,这里有一些例子和解释:这个问题其实并不是无趣的,检查一下我链接的问题。他也在从实例调用静态方法,您可能希望在此基础上添加一些内容,这意味着编译器将重写要在
类上执行的调用,对吗?为什么他们允许这样做?我宁愿给出这个事实,因为我知道规范。这里最有趣的问题是为什么Java创建者使用此功能。根据链接上的规范,静态方法不会从超级接口继承(可能是为了避免多继承冲突)。我想知道这种类继承的优点是什么。有趣是的,很有趣。