views:

420

answers:

4

Consider the following case:

public class A {
  public A() { b = new B(); }
  B b;
  private class B { }
}

From a warning in Eclipse I quote that: the java complier emulates the constructor A.B() by a synthetic accessor method. I suppose the compiler now goes ahead and creates an extra "under water" constructor for B.

I feel this is rather strange: why would class B not be visible as a.k.o. field in A? And: does it mean that class B is no longer private at run time? And: why behaves the protected keyword for class B different?

public class A {
  public A() { b = new B(); }
  B b;
  protected class B { }
}
A: 

You need to use

this.new B();
Ratnesh Maurya
sorry, but this.new B(); gives the same warning and behaviour.
Gerard
@Rats: that will make no difference to the problem in hand. The "this" qualification is implicit.
skaffman
+7  A: 

Inner classes are essentially a hack introduced in Java 1.1. The JVM doesn't actually have any concept of an inner class, and so the compiler has to bodge it. The compiler generates class B "outside" of class A, but in the same package, and then adds synthetic accessors/constructors to it to allow A to get access to it.

When you give B a protected constructor, A can access that constructor since it's in the same package, without needing a synthetic constructor to be added.

skaffman
+1 very good response
dfa
OK, I see it. For me this means I will avoid the use of inner classes like in the example, it can only lead to confusion.
Gerard
I wouldn't let it bother you. That particular compiler warning isn't really much use to anyone, synthetic methods are used all the time with inner classes, and have no significant impact.
skaffman
IMHO the synthetic methods were an unnecessary addition to the language. Just using package scope for the "private" members (which the compiler does under the hood anyway) was a satisfactory solution.
finnw
but the members are still "private" for the other classes in the package...
Carlos Heuberger
+1  A: 

The access of class B and its constructor do not have to be the same. You can have a private inner class with a package-scope constructor, and this is what I usually do.

public class A {
  public A() { b = new B(); }
  B b;
  private class B {
    B() { }
  }
}
finnw