Private constructor in abstract class

允我心安 提交于 2019-11-29 12:16:22

问题


In Java what is the purpose of using private constructor in an abstract class?

In a review I got this question, and I am curious, for what situation we need to use the constructor in such way?

I think it can be used in pair with another constructor in abstract class, but this is very trivial. Also it can be used for constructing static inner classes which will excend abstract class.

Maybe there is more elegant usage?


回答1:


If the private constructor is the only constructor of the class, then the reason is clear: to prevent subclassing. Some classes serve only as holders for static fields/methods and do not want to be either instantiated or subclassed. Note that the abstract modifier is in this case redundant—with or without it there would be no instantiation possible. As @JB Nizet notes below, the abstract modifier is also bad practice because it sends wrong signals to the class's clients. The class should in fact have been final.

There is another use case, quite rare though: you can have an abstract class with only private constructors that contains its own subclasses as nested classes. This idiom makes sure those nested classes are the only subclasses. In fact, enums in Java use just this idiom.

If there are other constructors around, well then there's really nothing special about the private constructor. It gets used in an abstract class just as in any other.




回答2:


Only thing I can think of is reusing common code shared by the other (protected) constructors. They could then call the private constructor in their first line.




回答3:


Sometimes, the default no-arg constructor is made private, and another constructor which accepts arguments is provided. This constructor might then invoke other private constructor(s) . This forces implementations to supply these arguments, which might ensure some variable is always initialized, although this is not common practice (in my experience). If this is the requirement, you would be better off checking your variables and throwing an IllegalArgumentExeption, explaining why the variable needs to be initialized.

If you create an abstract class with only private constructors, the class is practically useless as no instances can ever be created. If the intention is to create a utility class with only static methods (like the Math class in the java.lang package), private constructors are acceptable, however the class should be marked final instead, as marking the class as abstract implies the class is to be extended.




回答4:


  1. As mentioned, to be used as a common, internal-use only constructor.

  2. Abstract or not abstract, it's not uncommon to declare a private default constructor on a class containing only static public methods [helper methods] to prevent instantiating the class.




回答5:


no other elegant use is possible




回答6:


A private constructor in an abstract class can also serve the purpose of sealed classes (like in Scala or Kotlin etc.). Since you can still provide subclasses from within the abstract class, but outsiders cannot extend/implement (as @Marko Topolnik answered).

It does look like we will be getting sealed interface to more cleanly support this. See https://openjdk.java.net/jeps/8222777




回答7:


A final class with only private constructors is a design used by singletons and multitons.

An abstract class which has only private constructors is the only way I've seen to prevent a class from being instantiated. I have seen it used to create utility classes (which only have static methods and/or members).

As for setting up user expectations I see that https://docs.oracle.com/javase/tutorial/java/IandI/abstract.html states "Abstract classes cannot be instantiated, but they can be subclassed." I note that it does not state any intention that they are expected to be subclassed.

I also note however that viewing some Java source code I find the following designs are used (none of which are abstract classes with only private constructors):

  • Final utility classes with private constructors
    • http://developer.classpath.org/doc/java/lang/Math-source.html
    • http://developer.classpath.org/doc/java/lang/System-source.html
  • Final utility classes with private constructors which throw exceptions
    • http://hg.openjdk.java.net/jdk8/jdk8/jdk/file/687fd7c7986d/src/share/classes/java/util/Objects.java
  • Neither abstract nor final utility classes with private constructors
    • http://hg.openjdk.java.net/jdk8/jdk8/jdk/file/687fd7c7986d/src/share/classes/java/util/ArrayPrefixHelpers.java
    • http://hg.openjdk.java.net/jdk8/jdk8/jdk/file/687fd7c7986d/src/share/classes/java/util/Arrays.java
    • https://hg.openjdk.java.net/jdk8/jdk8/jdk/file/687fd7c7986d/src/share/classes/java/util/Collections.java
    • http://hg.openjdk.java.net/jdk8/jdk8/jdk/file/687fd7c7986d/src/share/classes/java/util/FormattableFlags.java
  • Looks like a utility, but apparently can be instantiated (no private constructors)
    • http://hg.openjdk.java.net/jdk8/jdk8/jdk/file/687fd7c7986d/src/share/classes/java/util/ArraysParallelSortHelpers.java


来源:https://stackoverflow.com/questions/11625635/private-constructor-in-abstract-class

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!