Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Static member class - declare class private and class member package-private?

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?

like image 964
helpermethod Avatar asked May 27 '10 10:05

helpermethod


1 Answers

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.

like image 142
aioobe Avatar answered Nov 15 '22 04:11

aioobe