Java中的构造函数可以是私有的吗?

时间:2010-05-12 04:26:30

标签: java constructor private

构造函数可以是私有的吗?私有构造函数如何有用?

16 个答案:

答案 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;
     }
}

修改
从几年后看这个答案,我想指出这个答案既不完整也有点极端。单身人士确实是一种反模式,一般应尽可能避免;然而,除了单身人士之外,私人建设者还有很多用途,我的回答只有一个。

给出一些使用私有构造函数的案例:

  1. 创建一个只能是相关静态函数集合的不可实例化的类(这基本上是一个单例,但如果它是无状态的,静态函数严格依赖于参数而不是类状态,则不是尽管我的早期自己似乎暗示了一种不合理的方法,但是当使用一个依赖注入的接口时,通常会在实现需要大量依赖关系或其他形式的上下文时更容易维护API。

  2. 当有多种不同的方法来创建对象时,私有构造函数可以更容易理解构造它的不同方式(例如,哪个更易读new ArrayList(5)或{{1 },ArrayList.createWithCapacity(5)ArrayList.createWithContents(5))。换句话说,私有构造函数允许您提供其名称更易理解的工厂函数,然后使构造函数私有,确保人们只使用更不言而喻的名称。这也常用于the builder pattern。例如:

    ArrayList.createWithInitialSize(5)

答案 1 :(得分:88)

我希望有人会提到这个(第二点),但是......私有构造函数有三种用途:

  • 在以下情况下阻止对象外部的实例化:

    • 工厂方法
    • static-methods-only(utility)class
    • 仅限常数类
  • 防止下沉(延伸)。如果只创建一个私有构造函数,则没有类可以扩展您的类,因为它无法调用super()构造函数。这是final

  • 的某种同义词
  • 重载的构造函数 - 由于重载方法和构造函数,有些可能是私有的,有些可能是公共的。特别是在您在构造函数中使用非公共类的情况下,您可以创建一个公共构造函数,该构造函数创建该类的实例,然后将其传递给私有构造函数。

答案 2 :(得分:24)

是的,它可以。将存在私有构造函数以防止实例化类,或者因为构造仅在内部发生,例如,工厂模式。有关详细信息,请参阅here

答案 3 :(得分:16)

这样您就可以控制类的实例化方式。如果您将构造函数设为私有,然后创建一个返回类的实例的可见构造函数方法,则可以执行诸如限制创建数量(通常保证只有一个实例)或回收实例或其他与构造相关的任务的操作

执行new x()永远不会返回null,但使用工厂模式,您可以返回null,甚至返回不同的子类型。

您也可以将它用于没有实例成员或属性的类,只使用静态成员 - 就​​像在实用程序函数类中一样。

答案 4 :(得分:9)

好吧,如果一个类中的所有方法都是静态的,那么私有构造函数是个好主意。

答案 5 :(得分:6)

私有构造函数可以在Java中进行定义,原因如下

  1. 要控制Java对象的实例化,它不允许您创建对象的实例。

  2. 它不允许该课程为Subclassed

  3. 这在实现单例模式时具有特殊优势,使用了私有的contstructors,并且可以控制为整个应用程序创建实例。

  4. 当你想要一个定义了所有常量的类并且不再需要它的实例时,我们将该类声明为私有构造函数。

答案 6 :(得分:5)

私有构造函数用于阻止实例初始化,例如您在java中使用的Math final类。 Singleton也使用私有构造函数

答案 7 :(得分:4)

是。类可以有私有构造函数。甚至抽象类也可以有私有构造函数。

通过使构造函数成为私有,我们阻止该类被实例化以及该类的子类化。

以下是私有构造函数的一些用法:

  1. Singleton Design Pattern
  2. To limit the number of instance creation
  3. To give meaningful name for object creation using static factory method
  4. Static Utility Class or Constant Class
  5. To prevent Subclassing
  6. Builder Design Pattern因此creating immutable classes

答案 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 明确指出,应该阻止用户访问“标准构造函数”以外的构造函数,并且应该强制使用静态初始化函数来强调“你所做的可能没有错,但它与此类的预期用法不同"

[他没有使用这个确切的措辞,我试图将其压缩到这个定义中 - 对不起罗伯特 :^) ]

作为旁注,完全可以将类中的唯一构造函数(又名标准构造函数)完全声明为私有,并让静态函数返回一个类实例 - 请参阅单例模式。非常不鼓励实现单例模式,除非某些用例仅在一个方向上进行通信,例如编写记录器类时