15

在 Java 中,在抽象类中使用私有构造函数的目的是什么?

在评论中我得到了这个问题,我很好奇,在什么情况下我们需要以这种方式使用构造函数?

我认为它可以与抽象类中的另一个构造函数配对使用,但这非常微不足道。它还可以用于构造超出抽象类的静态内部类。

也许有更优雅的用法?

4

7 回答 7

35

如果private构造函数是类的唯一构造函数,那么原因很明确:防止子类化。某些类仅用作静态字段/方法的持有者,并且不希望被实例化或子类化。请注意,abstract在这种情况下,修饰符是多余的——不管有没有它,都不可能实例化。正如@JB Nizet 在下面指出的那样,abstract修饰符也是不好的做法,因为它向班级的客户发送了错误的信号。该类实际上应该是final.

还有另一个用例,虽然非常罕见:您可以拥有一个abstract class包含其自己的子类作为嵌套类的private构造函数。这个习惯用法确保那些嵌套类是唯一的子类。事实上,Java 中的 s 就是使用这个习语。enum

如果周围还有其他构造函数,那么构造函数实际上并没有什么特别之处privateabstract就像在任何其他课程中一样,它可以在课程中使用。

于 2012-07-24T07:34:27.450 回答
6

我唯一能想到的就是重用其他(受保护的)构造函数共享的公共代码。然后他们可以在第一行调用私有构造函数。

于 2012-07-24T07:00:37.900 回答
3

有时,默认的无参数构造函数被设为私有,并提供另一个接受参数的构造函数。然后,此构造函数可能会调用其他私有构造函数。这会强制实现提供这些参数,这可能会确保始终初始化某些变量,尽管这不是常见的做法(根据我的经验)。如果这是要求,你最好检查你的变量并抛出一个IllegalArgumentExeption,解释为什么需要初始化变量。

如果您创建一个只有私有构造函数的抽象类,那么该类实际上是无用的,因为永远无法创建任何实例。如果打算创建一个只有静态方法的实用程序类(如包Math中的类java.lang),则可以接受私有构造函数,但是应该将类标记为 final,因为将类标记为抽象意味着该类将被扩展。

于 2012-07-24T07:08:13.683 回答
2
  1. 如前所述,用作通用的、仅供内部使用的构造函数。

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

于 2012-07-24T07:17:53.757 回答
0

没有其他优雅的用途是可能的

于 2012-07-24T07:00:15.257 回答
0

抽象类中的私有构造函数也可以用于sealed类的目的(如 Scala 或 Kotlin 等)。由于您仍然可以从抽象类中提供子类,但外人无法扩展/实现(正如@Marko Topolnik 回答的那样)。

看起来我们将sealed interface更加干净地支持这一点。见https://openjdk.java.net/jeps/8222777

于 2019-06-28T10:06:53.117 回答
0

只有私有构造函数的最终类是单例和多例使用的设计。

只有私有构造函数的抽象类是我见过的防止类被实例化的唯一方法。我已经看到它用于创建实用程序类(只有静态方法和/或成员)。

至于设置用户期望,我看到https://docs.oracle.com/javase/tutorial/java/IandI/abstract.html声明“抽象类不能被实例化,但它们可以被子类化。” 我注意到它并没有说明它们被分类的任何意图。

然而,我还注意到,查看一些 Java 源代码,我发现使用了以下设计(它们都不是只有私有构造函数的抽象类):

于 2019-11-19T13:24:43.763 回答