简体   繁体   English

一个类可以同时具有公共和私有构造函数吗?

[英]Can a class have both public and private constructor?

I came across a scenario, where I need a public and a private constructor. 我遇到了一个需要公共和私有构造函数的场景。 A private constructor is needed to set the private field whose type is a private inner class. 需要一个私有构造函数来设置其类型为私有内部类的私有字段。 Is this encoraged or discouraged ? 这是包庇还是不鼓励? Else what is a better solution for a scenario listed below ? 对于下面列出的方案,还有什么更好的解决方案?

Please read the comment, which supports my question more meaningfully. 请阅读评论,它更有意义地支持了我的问题。 Thanks, 谢谢,

public class CopyTree { 
    private TreeNode root;

    public Copytree() { }

    //  private CopyTree(TreeNode root) { this.root = root; }

    private static class TreeNode {
       TreeNode left;
        TreeNode right;
        Integer element;
        TreeNode(TreeNode left, TreeNode right, Integer element) {
            this.left = left;
            this.right = right;
            this.element = element;
    }
}

public CopyTree copyTree() {
    CopyTree ct = new CopyTree();
    ct.root = copyTree(root);  // <---- QUESTION:  Any cleaner solution ?? 
    // cleaner solution appears to be a private constructor
    // eg: CopyTree ct = new CopyTree(copyTree(root));  But can public and private constructor     coexist together ?
    return ct;
}

private TreeNode copyTree(TreeNode binaryTree) {
    TreeNode copy = null;
    if (binaryTree != null) {
        copy = new TreeNode(null, null, binaryTree.element);
        copy.left =  copyTree(binaryTree.left); 
        copy.right = copyTree(binaryTree.right);
    }
    return copy;
}

Can a class have both public and private constructor? 一个类可以同时具有公共和私有构造函数吗?

Yes, it is possible. 对的,这是可能的。

A private constructor is needed to set the private field whose type is a private inner class. 需要一个私有构造函数来设置其类型为私有内部类的私有字段。 Is this encouraged or discouraged ? 是鼓励还是劝阻?

It depends on the situation. 这取决于实际情况。 Whether you want other class to initialize the state of your object or not. 是否要其他类初始化对象的状态。 Here I think you have created class CopyTree to return the Copy of Tree which is a private class. 在这里,我认为您已经创建了类CopyTree来返回树的副本,这是一个私有类。 So TreeNode class would be encapsulated, hence it leaves you with option of using private constructor capture idiom. 因此TreeNode类将被封装,因此它为您提供了使用私有构造函数捕获惯用语的选项。

what is a better solution for a scenario listed below ? 下面列出的方案有什么更好的解决方案?

In my view private constructor capture idiom is the better solution. 在我看来,私有构造函数捕获成语是更好的解决方案。

For more information: 想要查询更多的信息:

you could search for private constructor capture idiom . 您可以搜索私有构造函数捕获惯用语

An example is given in Solution 53 of Java Puzzlers : Java Puzzlers的解决方案53中给出了一个示例:

Puzzle 53: Do Your Thing 难题53:做你的事

Now it's your turn to write some code. 现在该轮到您编写一些代码了。 Suppose that you have a library class called Thing whose sole constructor takes an int parameter: 假设您有一个名为Thing的库类,其唯一的构造函数带有一个int参数:

public class Thing {    
    public Thing(int i) { ... }
        ...
    }

A Thing instance provides no way to get the value of its constructor parameter. Thing实例无法获取其构造函数参数的值。 Because Thing is a library class, you have no access to its internals, and you can't modify it. 因为Thing是一个库类,所以您无法访问其内部,也无法对其进行修改。 Suppose that you want to write a subclass called MyThing, with a constructor that computes the parameter to the superclass constructor by invoking the method SomeOtherClass.func(). 假设您要编写一个名为MyThing的子类,该子类的构造函数可以通过调用SomeOtherClass.func()方法来计算超类构造函数的参数。 The value returned by this method changes unpredictably from call to call. 此方法返回的值在每次调用之间都会发生不可预测的变化。 Finally, suppose that you want to store the value that was passed to the superclass constructor in a final instance field of the subclass for future use. 最后,假设您要将传递给超类构造函数的值存储在子类的最终实例字段中,以备将来使用。 This is the code that you'd naturally write: 这是您自然会编写的代码:

public class MyThing extends Thing {
    private final int arg;
    public MyThing() {
        super(arg = SomeOtherClass.func());
        ...
    }
    ...
}

Unfortunately, it isn't legal. 不幸的是,这是不合法的。 If you try to compile it, you'll get an error message that looks something like this: 如果尝试对其进行编译,则会收到一条类似以下内容的错误消息:

MyThing.java:
  can't reference arg before supertype constructor has been called
        super(arg = SomeOtherClass.func());
                 ^

How can you rewrite MyThing to achieve the desired effect? 如何重写MyThing以达到预期的效果? The MyThing() constructor must be thread-safe: Multiple threads may invoke it concurrently. MyThing()构造函数必须是线程安全的:多个线程可以同时调用它。

Solution 53: Do Your Thing 解决方案53:做你的事

You could try to stash the result of the invocation SomeOtherClass.func() in a static field prior to invoking the Thing constructor. 您可以在调用Thing构造函数之前尝试将调用SomeOtherClass.func()的结果存储在静态字段中。 This solution is workable but awkward. 该解决方案是可行的,但是很尴尬。 In order to achieve thread-safety, you must synchronize access to the stashed value, which requires unimaginable contortions. 为了实现线程安全,必须同步访问隐藏值,这需要无法想象的扭曲。 Some of these contortions can be avoided by using a thread-local static field (java.util.ThreadLocal), but a much better solution exists. 通过使用线程局部静态字段(java.util.ThreadLocal)可以避免其中一些扭曲,但是存在更好的解决方案。 The preferred solution is inherently thread-safe as well as elegant. 首选的解决方案本质上是线程安全且美观的。 It involves the use of second, private constructor in MyThing: 它涉及在MyThing中使用第二个私有构造函数:

public class MyThing extends Thing {
    private final int arg;

    public MyThing() {
        this(SomeOtherClass.func());
    }

    private MyThing(int i) {
        super(i);
        arg = i;
   }
}

This solution uses an alternate constructor invocation. 此解决方案使用备用构造函数调用。 This feature allows one constructor in a class to chain to another constructor in the same class. 此功能允许类中的一个构造函数链接到同一类中的另一个构造函数。 In this case, MyThing() chains to private constructor MyThing(int), which performs the required instance initialization. 在这种情况下,MyThing()链接到私有构造函数MyThing(int),后者执行所需的实例初始化。 Within the private constructor, the value of expression SomeOtherClass.func() has been captured in the parameter i and can be stored in the final field param after the superclass constructor returns. 在私有构造函数中,表达式SomeOtherClass.func()的值已在参数i中捕获,并且可以在超类构造函数返回后存储在最终字段参数中。

A class can be prevented from being explicity instantiated by its callers using Private constructors. 可以防止使用私有构造函数的调用者显式实例化一个类。

Where private constructors are useful, 在私有构造函数有用的地方,

  • classes containing only static utility methods 仅包含静态实用程序方法的类
  • classes containing only constants 仅包含常量的类
  • type safe enumerations 输入安全枚举
  • singletons 单身人士

Where they prove to be a disadvantage (not limited to below points. List may grow) 在被证明是不利的地方(不仅限于以下几点。清单可能会增加)

  • Classes without public or protected constructors cannot be subclassed. 没有公共或受保护的构造函数的类不能被子类化。
  • They are not readily distinguishable from other static methods. 它们不易与其他静态方法区分开。

You can use both private and public constructor only in following way. 您只能通过以下方式使用私有和公共构造函数。 But you can't use both for no argument constructor or same argument type. 但是,不能将两者都用于没有参数的构造函数或相同的参数类型。

public class MyClass {
private MyClass(){

}
public MyClass(int i){

}
}

Judging from your commented-out code, you have already tried it and it worked. 从注释掉的代码来看,您已经尝试过了并且可以正常工作。 Therefore I can only confirm your finding: yes, the private constructor can coexist with the public one, and yes, it seems like a better solution since more initialization is done before receiving the reference to the new object. 因此,我只能确认您的发现:是的,私有构造函数可以与公共的构造函数共存,是的,这似乎是一种更好的解决方案,因为在接收到对新对象的引用之前要进行更多的初始化。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 java内部类私有构造函数,public成员 - java inner class private constructor, public members Java用Package Private Constructor继承公共类 - Java Inheriting a public class with Package Private Constructor 为什么只有使用 static 方法的 class 会出现错误:“Add a private constructor to hide the implicit public one.”? - Why does only the class with the static method have the error: “Add a private constructor to hide the implicit public one.”? 私有内部类的构造函数应该声明为public还是private? - Should the constructor of a private inner class be declared public or private? 从Main呼叫私人班级。 都在公共课 - Call Private Class from Main. Both in Public Class 一个类可以没有构造函数吗? - Can a class have no constructor? 为什么Calendar类没有公共构造函数? - Why does the Calendar class not have a public constructor? 使用公共构造函数 Java 声明一个私有 static 嵌套 class? - Declare a private static nested class with a public constructor Java? 当类被声明为包私有时,我们应该声明一个公共构造函数吗? - Should we declare a public constructor when the class is declared as package private? 既然抽象的 class 可以有一个公共的构造函数,为什么我们不能实例化它呢? - Since an abstract class can have a public constructor, why can't we instantiate it?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM