views:

100

answers:

2

Consider you have the following class

public class OuterClass {
    ...

    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?

+4  A: 

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.

aioobe
+1 Great answer. So should you always declare the static member class private/package-private/protected and leave the member fields package-private?
Helper Method
@Helper Method - No - see my answer.
Stephen C
You should do what's appropriate for the field in question. If it makes sense to have it private, make it private. Don't worry about performance issues etc, until it matters, and then profile the program in its entirety and see where you get the most out of optimization. (It will most certainly not be in cases like these.)
aioobe
+3  A: 

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.

Stephen C