13

When I have inner classes with private methods or fields the compiler has to create synthetic package-protected accessor methods to allow the outer class to access those private elements (and vice-versa).

To avoid that, I usually make all fields and methods and constructors package-protected instead of private.

But how about the visibility of the class itself? Is there an overhead to

 private static class A {
      A(){}
 }

versus

 static class A {
      A(){}
 }

Note that the constructor is package-protected in both cases, or does making the class private change that?

Thilo
  • 257,207
  • 101
  • 511
  • 656
  • 1
    possible duplicate of [Are Inner Classes lightweight?](http://stackoverflow.com/questions/4812464/are-inner-classes-lightweight) – templatetypedef Feb 10 '11 at 06:04
  • I wonder if the reduced visibility is leveraged by Hotspot in any way. ALso I wonder if java compilers can use this fact to exclude the class from consideration outside its scope of visibility. Interesting question, but I don't think there's any practical benefit. – Ron Feb 10 '11 at 06:49
  • @Ron: The compiler/IDE will certainly check the visibility and make compile errors or remove it from autocomplete. I am just wondering if anything is happening at runtime. – Thilo Feb 10 '11 at 07:00
  • Yeah I meant for faster compile & autocomplete generation – Ron Feb 10 '11 at 07:12

3 Answers3

18

Have you tried compiling it and comparing the byte code? Here are my results. For:

public class Example {
  public static void main(String[] args) {
    System.out.println("Hello world!");
  }
  private static class A {
    A(){}
  }
}

The above yields the following *.class files:

-rw-r--r--    1 michaelsafyan  staff   238 Feb 10 00:11 Example$A.class
-rw-r--r--    1 michaelsafyan  staff   474 Feb 10 00:11 Example.class

Now, if I move the class files, delete the private modifier, and recompile, I get:

 -rw-r--r--    1 michaelsafyan  staff   238 Feb 10 00:15 Example$A.class
 -rw-r--r--    1 michaelsafyan  staff   474 Feb 10 00:15 Example.class

If you look at the VM Spec on class files, you'll see that there is a constant-sized bit field for specifying the access modifiers, so it should not be any surprise that the generated files are the same size.

In short, your access modifiers won't affect the size of the generated byte code (it also should not have any performance impact, either). You should use the access modifier that makes the most sense.

I should also add that there is a slight difference if you change the inner class from being declared static to not being declared static, as it implies an additional field referencing the outer class. This will take up slightly more memory than if you declared the inner class static, but you'd be insane to optimize for this (use static where it makes sense, and where you need it to be non-static, make it non-static, but don't convolute your design just to save a pointer of memory here or there).

Michael Aaron Safyan
  • 93,612
  • 16
  • 138
  • 200
  • 3
    @Thilo, that's because you are not referencing anything in the outer class; if you needed to access the members or functions of the outer class, then there would be a legitimate reason to make it non-static. – Michael Aaron Safyan Feb 10 '11 at 05:40
10

There should be no performance difference between a private inner class and a non-private inner class.

There should be no performance difference between a static inner class (private or not) and an outer class.

There is a small performance difference between a static inner class and a non-static inner class. This difference is due to the fact that the non-static case has an hidden reference to the instance of its enclosing class. This is passed as an extra parameter to the inner classes constructor, and stored in a hidden variable.

Stephen C
  • 698,415
  • 94
  • 811
  • 1,216
  • 2
    And (to cover all cases) there is also a small performance difference when by-passing private visibility (of fields, methods, and constructors) with inner classes. – Thilo Feb 10 '11 at 07:04
  • 3
    @Thilo - Is there? Why? AFAIK, visibility rules are enforced by the compiler and by the verifier. By the time you get to execute (or JIT compile) the bytecodes, the visibility checks have all been done and there is no impact on performance. – Stephen C Feb 10 '11 at 07:25
  • 2
    The performance difference comes from accessing a private method through a compiler-generated synthetic wrapper method as opposed to accessing a package-protected method directly. – Thilo Feb 10 '11 at 07:27
  • 2
    @Thilo - um ... I see. Though I expect that the JIT compiler would inline the call. – Stephen C Feb 10 '11 at 07:39
4

It is very unlikely this will ever cause any significant slow-down.

One issue to be aware of with non-static inner classes is that they contain a reference to the instance of the enclosing class.

As such, this can cause 'memory leaks', as the enclosing instance can't be garbage collected. If you pass instances of inner classes out to callers, you are also passing out an instance of the enclosing class.

This is not the case with static inner classes!

Making all fields package protected to prevent synthetic methods is not advisable. You are giving up encapsulation which is a valuable thing to have. What are your concerns? Size of your class files for the additional code?

Jochen Bedersdorfer
  • 4,093
  • 24
  • 26
  • 1
    Encapsulation is most important at the package level, so I am not giving up much here. Outside packages (i.e. other people's code) cannot see the class either way. – Thilo Feb 10 '11 at 07:02
  • @Thilo Just because this is so right now, it does neccessarily not mean that this will stay forever this way. Encapsulation prepares you more for the unplanned than for the expected. – TheBlastOne Feb 10 '11 at 09:52
  • 1
    @TheBlastOne: Again, I am not breaking encapsulation at all here. Everything is still package-private. – Thilo Feb 10 '11 at 13:08
  • "Encapsulation is most important at the package level" There is no encapsulation on the package level. If you make your fields non-private, your class loses any control of what is inside them. Your objects then can enter an invalid state at any time. – Jochen Bedersdorfer Feb 10 '11 at 15:52
  • "If the outer class holds considerable data, it can lower the performance of the application." http://stackoverflow.com/a/8257808/521754 – despot May 02 '12 at 08:44
  • I don't see any relevant information to support this statement. I guess the author meant that leaking significant memory through non-static classes can slow down garbage collection. Yup. Might be. – Jochen Bedersdorfer May 02 '12 at 16:54