在Java中,在抽象类中使用私有构造函数的目的是什么?
在一篇评论中我得到了这个问题,我很好奇,我们需要以什么样的方式使用构造函数呢?
我认为它可以与抽象类中的另一个构造函数一起使用,但这非常简单。它也可以用于构造静态内部类,它将超越抽象类。
也许有更优雅的用法?
答案 0 :(得分:30)
如果private
构造函数是该类的 only 构造函数,那么原因很明显:防止子类化。某些类仅用作静态字段/方法的持有者,并且不希望实例化或子类化。请注意,abstract
修饰符在这种情况下是冗余的 - 有或没有它将不会有实例化。正如下面@JB Nizet所说,abstract
修饰符也是不好的做法,因为它向类的客户端发送了错误的信号。该课程实际上应该是final
。
还有另一个用例,非常罕见:您可以只有abstract class
只有private
构造函数,包含自己的子类作为嵌套类。这个习惯用法确保那些嵌套类是唯一的子类。实际上,Java中的enum
只使用这个习语。
如果还有其他构造函数,那么private
构造函数真的没有什么特别之处。它在abstract
类中使用,就像在任何其他类中一样。
答案 1 :(得分:6)
我唯一能想到的就是重用其他(受保护)构造函数共享的公共代码。然后他们可以在第一行调用私有构造函数。
答案 2 :(得分:2)
有时,默认的no-arg构造函数是私有的,并且提供了另一个接受参数的构造函数。然后,此构造函数可以调用其他私有构造函数。这迫使实现提供这些参数,这可能确保一些变量始终被初始化,尽管这不是常见的做法(根据我的经验)。如果这是要求,最好检查变量并抛出IllegalArgumentExeption
,解释为什么需要初始化变量。
如果使用仅私有构造函数创建抽象类,则该类实际上没用,因为无法创建任何实例。如果打算只用静态方法创建一个实用程序类(比如Math
包中的java.lang
类),那么私有构造函数是可以接受的,但是类应该标记为final,因为标记了类如抽象意味着要扩展类。
答案 3 :(得分:2)
如上所述,要用作常用的,仅供内部使用的构造函数。
抽象或不抽象,在仅包含静态公共方法[helper方法]的类上声明私有默认构造函数以防止实例化该类并不罕见。
答案 4 :(得分:0)
没有其他优雅的用途可以使用
答案 5 :(得分:0)
抽象类中的私有构造函数也可以满足sealed
类的目的(例如Scala或Kotlin等)。由于您仍然可以从抽象类中提供子类,但外部人员无法扩展/实现(如@Marko Topolnik回答)。
看来我们将获得sealed interface
来更加明确地支持这一点。参见https://openjdk.java.net/jeps/8222777
答案 6 :(得分:0)
只有私有构造函数的最终类是单例和多例使用的设计。
一个只有私有构造函数的抽象类是防止类实例化的唯一方法。我已经看到它用于创建实用程序类(仅具有静态方法和/或成员)。
关于设置用户期望,我看到https://docs.oracle.com/javase/tutorial/java/IandI/abstract.html指出“无法实例化抽象类,但可以可以子类化。我注意到,它并没有说明希望将它们归类。
但是我还注意到,查看一些Java源代码后,我发现使用了以下设计(没有一个是只有私有构造函数的抽象类):