Java内部类具有静态方法

时间:2019-06-24 22:44:59

标签: java inner-classes

我知道这个问题很简单,但是我真的想知道为什么为什么不去文档中假设我有这样的类。

public class OuterClass{
public static void main(String[] args)throws Exception{
    System.out.println(OuterClass.InnerClass.yearOfBorn);//works ok
    System.out.println(OuterClass.InnerClass.returnYearOfBorn());//not works
    System.out.println(OuterClass.InnerClass.returnYearOfBornAsPublic());//not works
}    
private final class InnerClass{
    private static final int yearOfBorn=13;
    private static int returnYearOfBorn(){
        return yearOfBorn;
    }        
    public static int returnYearOfBornAsPublic(){
        return yearOfBorn;
    }            
}

}

两个静态方法都抛出错误,指出

修饰符“ static”仅在常量变量声明中允许

我知道文档指出了

这在Java语言规范第8.1.3节中进行了描述

8.1.3内部类和封闭实例

An inner class is a nested class that is not explicitly or implicitly declared static. Inner classes may not declare static initializers (§8.7) or member interfaces. Inner classes may not declare static members, unless they are compile-time constant fields (§15.28).

但是我的问题是,diff是调用简单值还是属性而不是调用静态方法,而不管是public还是private?为什么可以调用属性而不是方法呢?

谢谢。

1 个答案:

答案 0 :(得分:2)

非静态内部类有一些特殊之处。

静态内部类没有它。顶级班没有。任何内部接口或枚举都没有它。

那个特殊的东西是一个看不见的领域。

此不可见字段的类型为Outer,它是final。它首先在其构造函数中初始化,是的,每个非静态内部类的构造函数都具有一个不可思议的参数,类型为Outer,用作该字段。

所以,当您写:

public class Outer {
    public class Inner {
    }
}

编译器将像实际编写代码一样编译此代码:

public class Outer {
    public static class Inner {
        private final Outer I_AM_MAGIC;

        public Inner(Outer outer) {
            this.I_AM_MAGIC = outer;
        }
    }
}

您可以使用javap反编译工具查看此隐藏的魔术;传递-verbose-private,您会看到这些。之所以存在这种魔力,是因为您可以从内部调用内部的实例方法,但是..在什么实例上调用这些外部方法?在那个隐藏的实例上!

请注意,这个奇特的,看似奇怪的代码:someOuter.new Inner()实际上是合法的Java代码。当从new Inner()的非静态上下文中调用Outer时,this实例作为不可见的参数传递给该构造函数,但是如果不存在,则代码不会完全可以编译...除非您使用outer.new Inner()语法。

编译器会阻止您向Inner添加静态方法的原因是,这被认为会引起一些混乱。基本上,您的问题的答案是:“没有充分的理由..只是...规范说Java编译器一定不允许它,因此javac不允许它。”

请注意,实际上,这些非静态内部类是令人困惑的事情。我强烈建议您自学始终使您的内部课程static,除非您真的知道自己在做什么。即使那样,三思而后行。然后再三思。然后,也许考虑制作一个非静态内部类。