构造函数可以是私有的吗?私有构造函数如何有用?
答案 0 :(得分:144)
是的,构造函数可以是私有的。这有不同的用途。一个这样的用途是singleton design anti-pattern,我会建议你反对使用。另一个更合理的用途是委托构造函数;你可以有一个构造函数,它有很多不同的选项,实际上是一个实现细节,所以你把它设为私有,但是你剩下的构造函数会委托给它。
作为委托构造函数的示例,以下类允许您保存值和类型,但它只允许您为类型的子集执行此操作,因此需要将通用构造函数设置为私有以确保仅允许使用的类型。公共私有构造函数有助于代码重用。
public class MyClass {
private final String value;
private final String type;
public MyClass(int x){
this(Integer.toString(x), "int");
}
public MyClass(boolean x){
this(Boolean.toString(x), "boolean");
}
public String toString(){
return value;
}
public String getType(){
return type;
}
private MyClass(String value, String type){
this.value = value;
this.type = type;
}
}
修改的
从几年后看这个答案,我想指出这个答案既不完整也有点极端。单身人士确实是一种反模式,一般应尽可能避免;然而,除了单身人士之外,私人建设者还有很多用途,我的回答只有一个。
给出一些使用私有构造函数的案例:
创建一个只能是相关静态函数集合的不可实例化的类(这基本上是一个单例,但如果它是无状态的,静态函数严格依赖于参数而不是类状态,则不是尽管我的早期自己似乎暗示了一种不合理的方法,但是当使用一个依赖注入的接口时,通常会在实现需要大量依赖关系或其他形式的上下文时更容易维护API。
当有多种不同的方法来创建对象时,私有构造函数可以更容易理解构造它的不同方式(例如,哪个更易读new ArrayList(5)
或{{1 },ArrayList.createWithCapacity(5)
,ArrayList.createWithContents(5)
)。换句话说,私有构造函数允许您提供其名称更易理解的工厂函数,然后使构造函数私有,确保人们只使用更不言而喻的名称。这也常用于the builder pattern。例如:
ArrayList.createWithInitialSize(5)
答案 1 :(得分:88)
我希望有人会提到这个(第二点),但是......私有构造函数有三种用途:
在以下情况下阻止对象外部的实例化:
防止下沉(延伸)。如果只创建一个私有构造函数,则没有类可以扩展您的类,因为它无法调用super()
构造函数。这是final
重载的构造函数 - 由于重载方法和构造函数,有些可能是私有的,有些可能是公共的。特别是在您在构造函数中使用非公共类的情况下,您可以创建一个公共构造函数,该构造函数创建该类的实例,然后将其传递给私有构造函数。
答案 2 :(得分:24)
是的,它可以。将存在私有构造函数以防止实例化类,或者因为构造仅在内部发生,例如,工厂模式。有关详细信息,请参阅here。
答案 3 :(得分:16)
是
这样您就可以控制类的实例化方式。如果您将构造函数设为私有,然后创建一个返回类的实例的可见构造函数方法,则可以执行诸如限制创建数量(通常保证只有一个实例)或回收实例或其他与构造相关的任务的操作
执行new x()
永远不会返回null
,但使用工厂模式,您可以返回null
,甚至返回不同的子类型。
您也可以将它用于没有实例成员或属性的类,只使用静态成员 - 就像在实用程序函数类中一样。
答案 4 :(得分:9)
好吧,如果一个类中的所有方法都是静态的,那么私有构造函数是个好主意。
答案 5 :(得分:6)
私有构造函数可以在Java中进行定义,原因如下
要控制Java对象的实例化,它不允许您创建对象的实例。
它不允许该课程为Subclassed
这在实现单例模式时具有特殊优势,使用了私有的contstructors,并且可以控制为整个应用程序创建实例。
当你想要一个定义了所有常量的类并且不再需要它的实例时,我们将该类声明为私有构造函数。
答案 6 :(得分:5)
是
私有构造函数用于阻止实例初始化,例如您在java中使用的Math final类。 Singleton也使用私有构造函数
答案 7 :(得分:4)
是。类可以有私有构造函数。甚至抽象类也可以有私有构造函数。
通过使构造函数成为私有,我们阻止该类被实例化以及该类的子类化。
以下是私有构造函数的一些用法:
答案 8 :(得分:3)
是的,类可以有一个私有构造函数。需要禁止从其他类访问构造函数,并在定义的类中保持可访问状态。
为什么您希望只在内部创建您的类的对象?这可以出于任何原因,但一个可能的原因是你想要实现一个单例。单例是一种设计模式,它只允许创建一个类的实例,这可以通过使用私有构造函数来完成。
答案 9 :(得分:2)
是的,它用于防止实例化并随后覆盖。这通常用于单身类。
答案 10 :(得分:2)
是构造函数可以是私有的。私有构造函数阻止任何其他类实例化私有构造函数
的示例public class CustomHttpClient {
private static HttpClient customHttpClient;
/** A private Constructor prevents any other class from instantiating. */
private CustomHttpClient() {
}}
答案 11 :(得分:1)
私有构造函数阻止调用者显式实例化类 查看有关PrivateConstructor
的更多信息答案 12 :(得分:1)
构造函数可以私有吗?私有构造函数有什么用?
是的。我认为这是另一个有用的例子:
//... ErrorType.java
public enum ErrorType {
X,
Y,
Z
}
//... ErrorTypeException.java
import java.util.*;
import java.lang.*;
import java.io.*;
//Translates ErrorTypes only
abstract public class ErrorTypeException extends Exception {
private ErrorTypeException(){}
//I don't want to expose thse
static private class Xx extends ErrorTypeException {}
static private class Yx extends ErrorTypeException {}
static private class Zx extends ErrorTypeException {}
// Want translation without exposing underlying type
public static Exception from(ErrorType errorType) {
switch (errorType) {
case X:
return new Xx();
case Y:
return new Yx();
default:
return new Zx();
}
}
// Want to get hold of class without exposing underlying type
public static Class<? extends ErrorTypeException> toExceptionClass(ErrorType errorType) {
switch (errorType) {
case X:
return Xx.class;
case Y:
return Yx.class;
default:
return Zx.class;
}
}
}
在上述情况下,它防止抽象类被静态内部类以外的任何派生类实例化。抽象类不能是最终的,但是在这种情况下,私有构造函数使其有效地终结于不是内部类的所有类
答案 13 :(得分:0)
拥有私有构造函数的基本思想是通过JVM从外部限制类的实例化,但是如果一个类具有参数构造函数,那么它推断出一个是故意实例化的。
答案 14 :(得分:0)
据我所知,我们可以将构造函数声明为私有,也可以
通过在类中使用静态方法获取该类的实例,我们在其中声明构造函数,然后返回类对象。我们将此方法分类为子类
通过使用classname.method
名称bcz,它是静态方法,我们将获得我们声明const的类的实例。
答案 15 :(得分:0)
受 Robert C. Martin 的“Clean Code”启发,我拼凑的示例:
/**
When overloading constructors, it is best practise to only allow the use of
different constructors than the standart one by explicitly enforcing the
useage of a static function to highlight the use of the overloaded constructor
in example:
Animal a = Animal.CreateInsectOrArachnia(2, "black", 8); //hatch a black widow
*/
class Animal
{
private int size;
private String color;
private int legs;
public Animal(int size, String color)
{
this.size = size;
this.color = color;
this.legs = 4;
}
//will prevent the instanciation of Animal with this constructor
private Animal(int size, String color, int legs)
{
this.size = size;
this.color = color;
this.legs = legs;
}
public static Animal CreateInsectOrArachnia(int size, String color, int legs)
{
return new Animal (size, color, legs);
}
}
Martins 明确指出,应该阻止用户访问“标准构造函数”以外的构造函数,并且应该强制使用静态初始化函数来强调“你所做的可能没有错,但它与此类的预期用法不同"
[他没有使用这个确切的措辞,我试图将其压缩到这个定义中 - 对不起罗伯特 :^) ]
作为旁注,完全可以将类中的唯一构造函数(又名标准构造函数)完全声明为私有,并让静态函数返回一个类实例 - 请参阅单例模式。非常不鼓励实现单例模式,除非某些用例仅在一个方向上进行通信,例如编写记录器类时