具有静态方法的Java内部类

问题描述 投票:0回答:1

我真的想知道为什么,而不是去看文档。假设我有这样的课:

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 内部类和封闭实例

内部类是未显式或隐式声明为静态的嵌套类。内部类不得声明静态初始值设定项(第 8.7 节)或成员接口。内部类不能声明静态成员,除非它们是编译时常量字段(第 15.28 节)。

但是我的问题是调用简单值或属性与调用静态方法(无论是公共还是私有)之间有什么区别?为什么可以调用属性但不能调用方法?

java inner-classes
1个回答
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
除非你真的知道你在做什么。即便如此,也要三思而后行。然后再三思。然后也许可以考虑制作一个非静态内部类。

© www.soinside.com 2019 - 2024. All rights reserved.