考虑你有以下课程
public class OuterClass {
...
private static class InnerClass {
int foo;
int bar;
}
}
我想我在某处读过(但不是官方的 Java 教程),如果我将静态成员类属性声明为私有,编译器必须生成某种访问器方法,以便外部类可以实际访问静态成员类的 (这实际上是一个包私有的顶级类)属性。
有什么想法吗?
考虑你有以下课程
public class OuterClass {
...
private static class InnerClass {
int foo;
int bar;
}
}
我想我在某处读过(但不是官方的 Java 教程),如果我将静态成员类属性声明为私有,编译器必须生成某种访问器方法,以便外部类可以实际访问静态成员类的 (这实际上是一个包私有的顶级类)属性。
有什么想法吗?
是的,这是真的。至少对于 Sun javac。看看下面的例子:
public class OuterClass {
public static void main(String... args) {
InnerClass.foo = 7;
System.out.println(InnerClass.foo);
}
private static class InnerClass {
private static int foo;
private static int bar;
}
}
$ javap -c OuterClass\$InnerClass
Compiled from "OuterClass.java"
class OuterClass$InnerClass extends java.lang.Object{
static int access$002(int);
Code:
0: iload_0
1: dup
2: putstatic #1; //Field foo:I
5: ireturn
static int access$000();
Code:
0: getstatic #1; //Field foo:I
3: ireturn
}
它定义了static int access$002(int)
用于设置值的 a 和static int access$000()
用于获取值的 a。setter 还返回值,大概是为了轻松 compile someVariable = InnerClass.foo = 5
。
$ javap -c OuterClass
Compiled from "OuterClass.java"
public class OuterClass extends java.lang.Object{
public OuterClass();
Code:
0: aload_0
1: invokespecial #1; //Method java/lang/Object."<init>":()V
4: return
public static void main(java.lang.String[]);
Code:
0: bipush 7
2: invokestatic #2; //Method OuterClass$InnerClass.access$002:(I)I
5: pop
6: getstatic #3; //Field java/lang/System.out:Ljava/io/PrintStream;
9: invokestatic #4; //Method OuterClass$InnerClass.access$000:()I
12: invokevirtual #5; //Method java/io/PrintStream.println:(I)V
15: return
}
在第 2 行和第 9 行,它分别调用 setter ( access$002
) 和 getter ( access$000
)。
另请注意,它仅在需要时才引入这些访问器方法。例如,该bar
字段从未从类外部访问过,因此编译器只为该foo
字段生成了一个 getter/setter。
有什么想法吗?
@aioobe 的回答表明您是正确的。
但是,它可能没有任何区别。JIT 编译器可能会将对访问器方法的调用内联,并且生成的本机代码将与简单的 fetch 相同。即使 JIT 编译器不这样做,性能损失在实际应用程序的上下文中也可能微不足道。
这就是说,通过使用与您真正想要表达的内容不同的访问修饰符来过早地“优化”代码是没有意义的。