Search code examples
javasingletonnested-class

Is it possible to have a nested singleton in java?


I was surprised to see that a private constructor of a nested class is still callable from the nesting class. For example:

 public class A{
      public void foo(){
           //private constructor of B
           //can be called from A
           B b = new B();
      }

      //nested class
      public static class B{
          private B(){
          }
      }
 }

Does this mean that there is no way to enforce the singleton pattern on a nested class? Or am I missing something fundamental here?


Solution

  • Does this mean that there is no way to enforce the singleton pattern on a nested class?

    It depends what you mean by "enforce".

    If you mean, can you get the compiler to prevent foo from breaking your 'singleton' invariant - then "No". (Or at least, not unless you make 'B' a non-nested class first ...)

    However, the outer class and the nested classes are all defined in the same source file, and should be considered as part of the same unit of abstraction. (And in fact, the fact that A.foo() can call A.B.B means the latter is true in a very real sense.) Therefore, it is the responsibility off A and everything within it to maintain the entire abstraction's invariants ... including singleton-ness of B.

    From that perspective, a foo method that breaks the invariant is no different to a hypothetical method on a non-nested "singleton" class that breaks the invariant; e.g.

    public Single {
        private static Single s = new Single();
        public static Single getInstance() { return s; }
        private Single() { ... }
    
        public void foo() {
            Single ss = new Single();  // breaks the invariant!!
            ...
        }
    }
    

    Note the problem ... in both cases ... is that the abstraction is breaking its own invariants.