java 抽象类中的私有构造函数
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/11625635/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Private constructor in abstract class
提问by Chris
In Java what is the purpose of using private constructor in an abstract class?
在 Java 中,在抽象类中使用私有构造函数的目的是什么?
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?
也许有更优雅的用法?
回答by Marko Topolnik
If the private
constructor is the onlyconstructor 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
.
如果private
构造函数是类的唯一构造函数,那么原因很明显:防止子类化。某些类仅用作静态字段/方法的持有者,并且不想被实例化或子类化。请注意,abstract
在这种情况下,修饰符是多余的——无论有没有它,都无法实例化。正如@JB Nizet 在下面指出的那样,abstract
修饰符也是不好的做法,因为它向类的客户端发送了错误的信号。该类实际上应该是final
.
There is another use case, quite rare though: you can have an abstract class
with only private
constructors that contains its own subclassesas nested classes. This idiom makes sure those nested classes are the only subclasses. In fact, enum
s in Java use just this idiom.
还有另一个用例,虽然非常罕见:您可以有一个abstract class
with only包含其子类作为嵌套类的private
构造函数。这个习惯用法确保那些嵌套的类是唯一的子类。事实上,Java 中的 s 就使用了这个习语。enum
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.
如果周围还有其他构造函数,那么构造函数真的没有什么特别之处private
。它abstract
就像在任何其他类中一样在一个类中使用。
回答by Thilo
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.
我唯一能想到的是重用其他(受保护的)构造函数共享的公共代码。然后他们可以在第一行调用私有构造函数。
回答by Jeshurun
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.
有时,默认的无参数构造函数是私有的,并提供另一个接受参数的构造函数。这个构造函数然后可能会调用其他私有构造函数。这会强制实现提供这些参数,这可能会确保始终初始化某些变量,尽管这不是常见做法(以我的经验)。如果这是要求,你最好检查你的变量并抛出一个IllegalArgumentExeption
,解释为什么需要初始化变量。
If you create an abstract class with onlyprivate 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.
如果你创建一个只有私有构造函数的抽象类,这个类实际上是没有用的,因为永远不能创建实例。如果打算创建一个只有静态方法的实用程序类(如包中的Math
类java.lang
),私有构造函数是可以接受的,但是该类应该标记为 final,因为将类标记为抽象意味着要扩展该类。
回答by Richard Sitze
As mentioned, to be used as a common, internal-use only constructor.
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.
如前所述,用作通用的、仅供内部使用的构造函数。
抽象或不抽象,在仅包含静态公共方法 [帮助方法] 的类上声明私有默认构造函数以防止实例化类并不少见。
回答by ManMohan Vyas
no other elegant use is possible
没有其他优雅的用途是可能的
回答by wilmol
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).
抽象类中的私有构造函数也可以用于sealed
类的目的(如在 Scala 或 Kotlin 等中)。由于您仍然可以从抽象类中提供子类,但局外人无法扩展/实现(正如@Marko Topolnik 所回答的那样)。
It does look like we will be getting sealed interface
to more cleanly support this. See https://openjdk.java.net/jeps/8222777
看起来我们将sealed interface
更加干净地支持这一点。见https://openjdk.java.net/jeps/8222777
回答by Kevin LeBlanc
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.htmlstates "Abstract classes cannot be instantiated, but they can besubclassed." I note that it does not state any intention that they are expected to be subclassed.
至于设置用户期望,我看到https://docs.oracle.com/javase/tutorial/java/IandI/abstract.html声明“抽象类不能被实例化,但它们可以被子类化。” 我注意到它没有说明任何希望它们被子类化的意图。
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):
然而,我还注意到,查看一些 Java 源代码时,我发现使用了以下设计(其中没有一个是只有私有构造函数的抽象类):
- Final utility classes with private constructors
- Final utility classes with private constructors which throw exceptions
- 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/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
- 看起来像一个实用程序,但显然可以实例化(没有私有构造函数)