Consider you have the following class
public class O开发者_Go百科uterClass {
...
private static class InnerClass {
int foo;
int bar;
}
}
I think I've read somewhere (but not the official Java Tutorial) that if I would declare the static member classes attributes private, the compiler had to generate some sort of accessor methods so that the outer class can actually access the static member class's (which is effectively a package-private top level class) attributes.
Any ideas on that?
Yes that's true. At least for the Sun javac. Have a look at the following example:
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
}
It defines a static int access$002(int)
for setting the value, and a static int access$000()
for getting the value. The setter also returns the value, presumably to easily 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
}
At line 2 and at line 9 it calls the setter (access$002
) and getter (access$000
) respectively.
Note also that it only introduces these accesser methods if they are needed. The bar
field for instance, was never accessed from outside the class, thus the compiler only generated a getter/setter for the foo
field.
Any ideas on that?
@aioobe's answer shows that you were correct.
However, it probably makes no difference. The chances are that the JIT compiler will inline the call to the accessor method and the resulting native code will be identical to a simple fetch. Even if the JIT compiler doesn't do that, the performance penalty is likely to be insignificant in the context of a realworld application.
What this says is that there is no point prematurely "optimizing" the code by using access modifiers that say something different to what you really want to express.
精彩评论