26

I am new to Java. I want to know what it is the use of public constructor in a private class. Private class inside the class can be initialized from the same class then what it is the use to make the constructor of private class to public?

public class MainActivity extends Activity {
     private class AcceptThread extends Thread {
        public AcceptThread() {

        }
    }
}
skiwi
  • 66,971
  • 31
  • 131
  • 216
Mick
  • 1,179
  • 5
  • 14
  • 24

2 Answers2

16

There doesn't seems to be any real use case for public or protected modifiers with private classes. If you have multiple classes in a single file though (but not nested or local), you need non-private constructors to instantiate the private classes.

// X.java

public class X {
    private Y y = new Y();
}

class Y {
    Y () {
        // if this were private, X wouldn't be able to create an instance of Y
    }
}

Actually default or protected visibility would be enough to create an instance in this case. All non-private modifiers allow you to create instances from other classes within the same package but practically have the same visibility.

  • The private class isn't visible to classes outside of the package, so public methods have no use here.
  • The private class can't be extended by classes outside of the package, so protected has no use either.
  • Even when using reflections, a public constructor is not accessible by default from other packages and will throw a IllegalAccessException. It checks the class visibility first, then the member visibility.

The default modifier is the most restrictive modifier that allows you to directly call the constructor from other classes, so package-private seems to be the most appropriate visibility for the constructor and also any other non-private methods. This also has the advantage that if you change the class visibility in the future, you don't accidentally expose the constructor or any methods to the public.

kapex
  • 28,903
  • 6
  • 107
  • 121
8

You know, I ask myself this question almost each time I make a private inner class, but I always assumed that there could be some (possibly contrived) reason for a public constructor. So @kapep 's answer got me tingling and encouraged to find ways to require a public constructor on a private inner class, but the more I think and experiment with it, the more I think the holes are plugged.

Possible angles, all of which failed me:

  • Serialisation: When unmarshalling an object whose superclass is not serializable, the superclass needs a no-arg constructor accessible from the subclass. So, protected should always suffice here.

  • Reflective tools: Code that uses reflection to get the inner class constructor through a returned instance. Fails because the type visibility is checked first, as @kapep pointed out, though it leaves a rather interesting error message:

    Exception in thread "main" java.lang.IllegalAccessException: Class A can not access a member of class contrived.B$C with modifiers "public"

  • Inner class extension shenanigans: Don't try this at home:

    package a;
    class Outer {
      private class Inner {
      }
    }
    
    package b;
    // compile error: Outer.Inner has private access in Outer
    class Extender extends a.Outer.Inner {
      Extender(a.Outer outer) {
        outer.super();
      }
    }
    

    Seemed promising at first, but I didn't get too far with that one.


In the end, I could not find a way to make a public constructor on a private inner class useful.

Then why is this technically legal despite having no use? Probably because the compiler automagically inserts a no-arg public constructor when no other constructor is provided. Hence the language should not disallow this constructs. More of an artefact than a reason, though.

JvR
  • 1,187
  • 8
  • 8