考虑您有以下课程
public class OuterClass {
...
private static class InnerClass {
int foo;
int bar;
}
}
我想我已经读过某个地方(但不是官方的Java Tutorial),如果我将静态成员类属性声明为private,则编译器必须生成某种访问器方法,以便外部类可以实际访问静态成员类(实际上是包 - 私有顶级类)属性。
有关于此的任何想法吗?
答案 0 :(得分:4)
是的,这是真的。至少对于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)
和用于获取值的static int access$000()
。 setter也返回值,可能是为了轻松编译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。
答案 1 :(得分:3)
有关于此的任何想法吗?
@ aioobe的回答表明你是对的。
然而,它可能没什么区别。很可能JIT编译器将内联对访问器方法的调用,并且生成的本机代码将与简单的提取相同。即使JIT编译器不这样做,在真实世界应用程序的上下文中,性能损失也可能是微不足道的。
这就是说没有意义通过使用与您真正想要表达的内容不同的访问修饰符过早地“优化”代码。