构造函数必须总是 public 吗?
Do constructors always have to be public?
我的第一个问题是 -
class Explain() {
public Explain() {
}
}
Constructor 是否应该始终声明为 public?
如果我创建一个 private
构造函数会怎么样。
我总是看到构造函数是隐式的 public
。那么为什么 private
构造函数有用呢?或者它根本没有用。因为没有人可以调用它,或者永远不会创建对象(因为 private
构造函数)!这是我的第二个问题。
不,构造函数可以是public
、private
、protected
或default
(根本没有访问修饰符) .
制作一些东西 private
并不意味着没有人可以访问它。这只是意味着 class 之外的任何人都无法访问它。所以 private
构造函数也很有用。
private
构造函数的用途之一是服务单例 classes。单例 class 是一种将对象创建数量限制为一个的单例。使用 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 Whosebug.");
}
public String getName() {
return name;
}
}
有关的更多信息access modifiers.
是的,构造函数可以有任何访问 specifier/access 修饰符。
私有构造函数可用于创建 singleton
classes.
单例 - 单例 class 是一个 class,其中只能在运行时创建一个对象(每个 JVM)。
单例的一个简单示例 class 是 -
class Ex {
private static Ex instance;
int a;
private Ex() {
a = 10;
}
public static Ex getInstance() {
if(instance == null) {
instance = new Ex();
}
return instance;
}
}
注意,对于上面的 class,获取对象(在这个 class 之外)的唯一方法是调用 getInstance() 函数,它只会创建一个实例并保留返回那个。
另请注意,这不是线程安全的。
构造函数可以是 public、默认的或私有的,这完全取决于您要用它做什么。
例如,如果您正在定义一个单例 class,您最好 隐藏(意思是将其设为私有,以便仅供 class 它所属的地方)构造函数以防止其他 classes 随意实例化你的 class。
您可能希望将其声明为默认值,比方说,出于测试目的,以便同一包中的测试用例可以访问它。
可以找到更详细的信息here
构造函数可以有各种访问修饰符。不同的访问修饰符在构造函数上的用法是不同的。
如果您希望从任何地方实例化 class,您可以创建一个构造函数 public
。
如果您希望继承 class 并实例化其继承的 class,则创建构造函数 protected
。
如果您希望 class 仅从它自己的成员(通常是静态块或静态方法)实例化,则可以创建构造函数 private
。这意味着您可以控制实例化 class 并在实例化上应用一些规则。私有构造函数的使用示例是单例设计模式。
构造函数 必须 在创建时至少受到保护甚至私有,例如,自定义工厂 类,例如:
public final class MyFactory {
private MyFactory(){} // this one prevents instances of your factory
}
public static void doSomething(){} // access that with MyFactory.doSomething
请注意,这只是一个示例,说明构造函数何时不应 public。
没有规定构造函数是public。通常我们定义它public只是因为我们也想从其他class中实例化它。
私有构造函数意味着,"i dont let anyone create my instance except me "。
所以通常当你想要一个单例模式时你会这样做。
以下是 JDK 中的 class,它使用了私有构造函数。
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() {
}
}
不,构造函数可以使用任何访问修饰符,包括 private。 (一个私人
constructor 意味着只有 class 本身的代码可以实例化一个对象
那种类型,所以如果私有构造函数 class 想要允许一个实例
在要使用的 class 中,class 必须提供允许访问从 class 中创建的实例的静态方法或变量。)
例子
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
我同意前面的回答,即单例是 class 具有私有构造函数的一个很好的例子。不过我会推荐一个不同的实现:一个线程安全的单例:
/**
* 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;
}
}
以线程安全的方式使用单例可以避免并行代码中的许多痛苦。
简单的解释就是如果class中没有构造函数,编译器会自动创建一个默认构造函数。
构造函数并不总是声明为public,它也可以是私有的、受保护的或默认的。
私有构造函数阻止 class 被其调用者完全清楚地 expressed/represented。在那种情况下,私有构造函数很有用。如果我们不需要 class 被子 classed,我们可以使用私有构造函数。
这些答案中的大多数都涉及单例或工厂 class。另一个私有构造函数出现的时间是(例如)在 java.lang.Math class 中,其中所有内容都是静态的,任何人都不应该调用构造函数(包括 class 本身)。通过拥有私有构造函数,您可以防止 class 之外的任何人调用构造函数。 (这不会阻止 class 中的某些人调用构造函数,但他们会违反自己的规则。)
其他人注意到构造函数可能具有访问修饰符;尚未提及的方面是构造函数上的方面修饰符控制构造的两个非常不同的方面,但不允许单独控制它们:
- 谁可以创建
ClassName
的 实例 以及他们可以使用哪些构造函数。
- 谁可以创建
ClassName
的 扩展 以及他们可以使用哪些构造函数。
Java 和 .NET 都要求同时回答这两个问题;如果 class 不是 final
(或 sealed
)并且允许外部代码使用构造函数来创建新实例,那么外部代码也可以完全自由地使用相同的构造函数创建派生类型的构造函数。
在许多情况下,class 仅具有包私有 (internal
) 构造函数可能是合适的,但公开 return 新的 public 方法实例。如果从头开始设计像 String
这样的类型,则可以使用这种方法;包含 String
的包可以将其定义为抽象类型,但包含具体的派生类型,如 AsciiString
和 UCS16String
,它们将内容存储为 byte[]
和 Char[]
,分别; return String
然后可以 return 派生方法之一,具体取决于字符串是否包含 ASCII 范围之外的字符。如果 String
和任何派生类型都没有在其包外公开任何构造函数,并且包内的所有派生类型的行为都应该像字符串一样,那么接收类型 String
的引用的代码可以期望它作为一个字符串表现得理智(例如,保证关于它的值的任何观察将永远保持真实)。但是,将构造函数暴露在包外会使派生类型以怪异的方式运行(例如,在检查和验证后更改它们的内容)。
从语法的角度来看,能够说 Fnord foo = new Fnord(123);
比必须说 Fnord foo = Fnord.Create(123);
好一点,但是 class Fnord
需要后一种语法可以更好地控制对象创建过程。
我的第一个问题是 -
class Explain() {
public Explain() {
}
}
Constructor 是否应该始终声明为 public?
如果我创建一个 private
构造函数会怎么样。
我总是看到构造函数是隐式的 public
。那么为什么 private
构造函数有用呢?或者它根本没有用。因为没有人可以调用它,或者永远不会创建对象(因为 private
构造函数)!这是我的第二个问题。
不,构造函数可以是public
、private
、protected
或default
(根本没有访问修饰符) .
制作一些东西 private
并不意味着没有人可以访问它。这只是意味着 class 之外的任何人都无法访问它。所以 private
构造函数也很有用。
private
构造函数的用途之一是服务单例 classes。单例 class 是一种将对象创建数量限制为一个的单例。使用 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 Whosebug.");
}
public String getName() {
return name;
}
}
有关的更多信息access modifiers.
是的,构造函数可以有任何访问 specifier/access 修饰符。
私有构造函数可用于创建 singleton
classes.
单例 - 单例 class 是一个 class,其中只能在运行时创建一个对象(每个 JVM)。
单例的一个简单示例 class 是 -
class Ex {
private static Ex instance;
int a;
private Ex() {
a = 10;
}
public static Ex getInstance() {
if(instance == null) {
instance = new Ex();
}
return instance;
}
}
注意,对于上面的 class,获取对象(在这个 class 之外)的唯一方法是调用 getInstance() 函数,它只会创建一个实例并保留返回那个。
另请注意,这不是线程安全的。
构造函数可以是 public、默认的或私有的,这完全取决于您要用它做什么。
例如,如果您正在定义一个单例 class,您最好 隐藏(意思是将其设为私有,以便仅供 class 它所属的地方)构造函数以防止其他 classes 随意实例化你的 class。
您可能希望将其声明为默认值,比方说,出于测试目的,以便同一包中的测试用例可以访问它。
可以找到更详细的信息here
构造函数可以有各种访问修饰符。不同的访问修饰符在构造函数上的用法是不同的。
如果您希望从任何地方实例化 class,您可以创建一个构造函数 public
。
如果您希望继承 class 并实例化其继承的 class,则创建构造函数 protected
。
如果您希望 class 仅从它自己的成员(通常是静态块或静态方法)实例化,则可以创建构造函数 private
。这意味着您可以控制实例化 class 并在实例化上应用一些规则。私有构造函数的使用示例是单例设计模式。
构造函数 必须 在创建时至少受到保护甚至私有,例如,自定义工厂 类,例如:
public final class MyFactory {
private MyFactory(){} // this one prevents instances of your factory
}
public static void doSomething(){} // access that with MyFactory.doSomething
请注意,这只是一个示例,说明构造函数何时不应 public。
没有规定构造函数是public。通常我们定义它public只是因为我们也想从其他class中实例化它。
私有构造函数意味着,"i dont let anyone create my instance except me "。 所以通常当你想要一个单例模式时你会这样做。
以下是 JDK 中的 class,它使用了私有构造函数。
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() {
}
}
不,构造函数可以使用任何访问修饰符,包括 private。 (一个私人 constructor 意味着只有 class 本身的代码可以实例化一个对象 那种类型,所以如果私有构造函数 class 想要允许一个实例 在要使用的 class 中,class 必须提供允许访问从 class 中创建的实例的静态方法或变量。)
例子
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
我同意前面的回答,即单例是 class 具有私有构造函数的一个很好的例子。不过我会推荐一个不同的实现:一个线程安全的单例:
/**
* 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;
}
}
以线程安全的方式使用单例可以避免并行代码中的许多痛苦。
简单的解释就是如果class中没有构造函数,编译器会自动创建一个默认构造函数。
构造函数并不总是声明为public,它也可以是私有的、受保护的或默认的。
私有构造函数阻止 class 被其调用者完全清楚地 expressed/represented。在那种情况下,私有构造函数很有用。如果我们不需要 class 被子 classed,我们可以使用私有构造函数。
这些答案中的大多数都涉及单例或工厂 class。另一个私有构造函数出现的时间是(例如)在 java.lang.Math class 中,其中所有内容都是静态的,任何人都不应该调用构造函数(包括 class 本身)。通过拥有私有构造函数,您可以防止 class 之外的任何人调用构造函数。 (这不会阻止 class 中的某些人调用构造函数,但他们会违反自己的规则。)
其他人注意到构造函数可能具有访问修饰符;尚未提及的方面是构造函数上的方面修饰符控制构造的两个非常不同的方面,但不允许单独控制它们:
- 谁可以创建
ClassName
的 实例 以及他们可以使用哪些构造函数。 - 谁可以创建
ClassName
的 扩展 以及他们可以使用哪些构造函数。
Java 和 .NET 都要求同时回答这两个问题;如果 class 不是 final
(或 sealed
)并且允许外部代码使用构造函数来创建新实例,那么外部代码也可以完全自由地使用相同的构造函数创建派生类型的构造函数。
在许多情况下,class 仅具有包私有 (internal
) 构造函数可能是合适的,但公开 return 新的 public 方法实例。如果从头开始设计像 String
这样的类型,则可以使用这种方法;包含 String
的包可以将其定义为抽象类型,但包含具体的派生类型,如 AsciiString
和 UCS16String
,它们将内容存储为 byte[]
和 Char[]
,分别; return String
然后可以 return 派生方法之一,具体取决于字符串是否包含 ASCII 范围之外的字符。如果 String
和任何派生类型都没有在其包外公开任何构造函数,并且包内的所有派生类型的行为都应该像字符串一样,那么接收类型 String
的引用的代码可以期望它作为一个字符串表现得理智(例如,保证关于它的值的任何观察将永远保持真实)。但是,将构造函数暴露在包外会使派生类型以怪异的方式运行(例如,在检查和验证后更改它们的内容)。
从语法的角度来看,能够说 Fnord foo = new Fnord(123);
比必须说 Fnord foo = Fnord.Create(123);
好一点,但是 class Fnord
需要后一种语法可以更好地控制对象创建过程。