建设者总是必须公开吗?

时间:2015-06-23 07:02:19

标签: java oop design-patterns constructor access-modifiers

我的第一个问题是 -

   class Explain() {
        public Explain() {
      }
   }

构造函数是否应始终声明为public?

如果我创建private构造函数,该怎么办?

我总是看到构造函数是隐含的public。那么为什么private构造函数有用呢?或者根本没用。因为没有人可以调用它,或者从不创建对象(因为private构造函数)!这是我的第二个问题。

11 个答案:

答案 0 :(得分:73)

不,构造函数可以是publicprivateprotecteddefault(根本没有访问修饰符)。

制作private并不代表任何人都无法访问它。这只意味着班上没有人可以访问它。所以private构造函数也很有用。

private构造函数的一个用途是提供单例类。单例类是将对象创建的数量限制为一个的类。使用private构造函数,我们可以确保一次只能创建一个以上的对象。

示例 -

public class Database {

    private static Database singleObject;
    private int record;
    private String name;

    private Database(String n) {
        name = n;
        record = 0;
    }

    public static synchronized Database getInstance(String n) {
        if (singleObject == null) {
            singleObject = new Database(n);
        }

        return singleObject;
    }

    public void doSomething() {
        System.out.println("Hello StackOverflow.");
    }

    public String getName() {
        return name;
    }
}

有关 access modifiers.

的更多信息

答案 1 :(得分:9)

是的,构造函数可以拥有任何访问说明符/访问修饰符。

私有构造函数对于创建singleton类非常有用。

Singleton - 单例类是一个只能在运行时创建单个对象的类(每个JVM)。

单例类的一个简单示例是 -

class Ex {
    private static Ex instance;
    int a;
    private Ex() {
        a = 10;
    }
    public static Ex getInstance() {
        if(instance == null) {
            instance = new Ex();
        }
        return instance;
    }
}

注意,对于上面的类,获取对象(在此类之外)的唯一方法是调用getInstance()函数,该函数只创建一个实例并继续返回。

另请注意,这不是线程安全的。

答案 2 :(得分:7)

构造函数可以是公共的,默认的或私有的,这完全取决于你想用它做什么。

例如,如果要定义Singleton类,则最好隐藏(意味着将其设置为私有,以便它仅对其所属的类可用)构造函数以防止其他类根据自己的意愿实例化你的课程。

您可能希望将其声明为默认值,例如,用于测试目的,以便同一个包中的测试用例可以访问它。

可以找到更详细的信息here

答案 3 :(得分:5)

没有规则将构造函数公开。通常我们将它定义为public只是因为我们想要从其他类中实例化它。

私有构造函数意味着,"我不允许任何人创建我的实例,除了我"。 所以通常情况下,当你想要单一模式时,你会这样做。

以下是JDK中使用私有构造函数的类。

public class Runtime {
    private static Runtime currentRuntime = new Runtime();

    public static Runtime getRuntime() {
        return currentRuntime;
    }

    // Don't let anyone else instantiate this class
    private Runtime() {
    }
}

答案 4 :(得分:5)

不,构造函数可以使用任何访问修饰符,包括私有。 (一个私人的 构造函数意味着只有类本身内的代码才能实例化一个对象 那种类型,所以如果私有构造函数类想要允许一个实例 要使用的类,该类必须提供一个静态方法或变量,允许访问从类中创建的实例。)

实施例

class Alpha {
   static String s = " ";
   protected Alpha() { s += "alpha "; }
 }
 class SubAlpha extends Alpha {
   private SubAlpha() { s += "sub "; }
 }
 public class SubSubAlpha extends Alpha {
   private SubSubAlpha() { s += "subsub "; }
   public static void main(String[] args) {
     new SubSubAlpha();
     System.out.println(s);
   }
 }

以上程序的输出将是

alpha subsub

答案 5 :(得分:4)

构造函数可以拥有所有类型的访问修饰符。在构造函数上使用不同的访问修饰符是不同的。

如果您希望从任何位置实例化类,您可以创建一个构造函数By lastRow=By.cssSelector("table#requisitionsTable tr:last-child"); driver.findElement(lastRow).getText();

如果希望继承类并实例化其继承的类,则创建构造函数public

如果希望仅通过静态块或静态方法从其自己的成员实例化类,则可以创建构造函数protected。这意味着您可以控制实例化类并在实例化上应用一些规则。私有构造函数的使用示例是单例设计模式。

答案 6 :(得分:4)

我同意以前的答案,Singleton是一个拥有私有构造函数的类的一个很好的例子。我会推荐一个不同的实现:一个线程安全的Singleton:

/**
 * Thread safe singleton
 */
public class Singleton {

    private static volatile Singleton instance = null;

    /**
     * Private constructor
     */
    private Singleton() {
    }

    /**
     * Gets the Instance of the Singleton in a thread safe way.
     * @return
     */
    public static Singleton getInstance() {
        if (instance == null) {
            synchronized (Singleton.class) {
                if (instance == null) {
                    instance = new Singleton();
                }
            }
        }
        return instance;
    }
}

以线程安全的方式使用单例可以避免并行代码中的很多痛苦。

答案 7 :(得分:3)

在创建自定义工厂类时,构造函数具有至少受到保护甚至是私有的,例如:

public final class MyFactory {
  private MyFactory(){} // this one prevents instances of your factory
}

public static void doSomething(){} // access that with MyFactory.doSomething

请注意,这只是一个显示构造函数何时不应公开的示例。

答案 8 :(得分:1)

这些答案中的大部分都是指单身人士或工厂阶级。另一次私有构造函数出现(例如)在java.lang.Math class中,其中一切都是静态的,没有人应该调用构造函数(包括类本身)。通过使用私有构造函数,可以防止类外的任何人调用构造函数。 (这不会阻止类中的某个人调用构造函数,但是他们会违反自己的规则。)

答案 9 :(得分:1)

其他人已经注意到构造函数可能有访问修饰符;尚未提到的一个方面是构造函数上的方面修饰符控制构造的两个非常不同的方面,但不允许它们单独控制:

  1. 允许谁创建ClassName实例以及允许使用的构造函数。
  2. 允许谁创建ClassName扩展以及允许使用的构造函数。
  3. Java和.NET都要求将这两个问题的答案放在一起;如果一个类不是final(或sealed)并且允许外部代码使用构造函数来创建新实例,那么外部代码也可以完全自由地使用相同的构造函数来创建派生类型。

    在许多情况下,类可能只适用于package-private(internal)构造函数,但是公开返回新实例的公共方法。如果从头开始设计类似String的类型,则可以使用这种方法;包含String的包可以将其定义为抽象类型,但包括具体的派生类型,如AsciiStringUCS16String,将其内容存储为byte[]Char[],分别;返回String的方法可以返回其中一个派生词,具体取决于字符串是否包含ASCII范围之外的字符。如果String和任何派生类型都没有公开其包之外的任何构造函数,并且包中的所有派生类型都表现为行为,那么接收类型为String的引用的代码可能会出现它表现得像一个字符串(例如,保证任何有关其价值的观察将永远保持真实)。然而,将构造函数暴露在包之外会使派生类型以奇怪和奇怪的方式表现(例如,在它们经过检查和验证后更改其内容)。

    从语法的角度来看,能够说Fnord foo = new Fnord(123);比说Fnord foo = Fnord.Create(123);更好一点,但需要后一种语法的类Fnord可以更好地控制对象创建过程。

答案 10 :(得分:0)

简单的解释是,如果类中没有构造函数,编译器会自动创建一个默认构造函数。

构造函数并不总是声明为public,也可以是private,protected或default。

私有构造函数阻止类被其调用者完全清楚地表达/表示。在这种情况下,私有构造函数是有用的。如果我们不需要我们的类被分类,我们可以使用私有构造函数。