简体   繁体   English

抽象类中的私有构造函数

[英]Private constructor in abstract class

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?也许有更优雅的用法?

If the private constructor is the only constructor of the class, then the reason is clear: to prevent subclassing.如果private构造函数是类的唯一构造函数,那么原因很明确:防止子类化。 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.请注意,在这种情况下, abstract修饰符是多余的——有或没有它都不可能进行实例化。 As @JB Nizet notes below, the abstract modifier is also bad practice because it sends wrong signals to the class's clients.正如@JB Nizet 在下面指出的那样, abstract修饰符也是一种不好的做法,因为它向类的客户端发送了错误的信号。 The class should in fact have been final .该类实际上应该是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.还有另一个用例,虽然很少见:你可以有一个只有private构造函数的abstract class ,它包含自己的子类作为嵌套类。 This idiom makes sure those nested classes are the only subclasses .这个习惯用法确保那些嵌套类是唯一的子类 In fact, enum s in Java use just this idiom.事实上,Java 中的enum就是使用这个习惯用法。

If there are other constructors around, well then there's really nothing special about the private constructor.如果周围还有其他构造函数,那么private构造函数真的没有什么特别之处。 It gets used in an abstract class just as in any other.就像在任何其他abstract类中一样,它在抽象类中使用。

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.然后他们可以在第一行调用私有构造函数。

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 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.如果打算创建一个仅包含静态方法的实用程序类(如java.lang包中的Math类),私有构造函数是可以接受的,但是该类应该标记为 final,因为将类标记为抽象意味着该类是被延长。

  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.抽象或不抽象,在仅包含静态公共方法 [辅助方法] 的类上声明私有默认构造函数以防止实例化该类的情况并不少见。

no other elegant use is possible没有其他优雅的用途是可能的

A private constructor in an abstract class can also serve the purpose of sealed classes (like in Scala or Kotlin etc.).抽象类中的私有构造函数也可以用于sealed类(如 Scala 或 Kotlin 等)。 Since you can still provide subclasses from within the abstract class, but outsiders cannot extend/implement (as @Marko Topolnik answered).由于您仍然可以从抽象类中提供子类,但外部人员无法扩展/实现(正如@Marko Topolnik 回答的那样)。

It does look like we will be getting sealed interface to more cleanly support this.看起来我们将获得sealed interface以更干净地支持它。 See https://openjdk.java.net/jeps/8222777参见https://openjdk.java.net/jeps/8222777

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."至于设置用户期望,我看到https://docs.oracle.com/javase/tutorial/java/IandI/abstract.html指出“抽象类不能被实例化,但它们可以被子类化。” 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):但是我也注意到,查看一些 Java 源代码我发现使用了以下设计(它们都不是只有私有构造函数的抽象类):

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM