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

Java 类可以同时具有公共构造函数和私有构造函数吗?,java,private,public,Java,Private,Public,我遇到了一个场景,我需要一个公共构造函数和一个私有构造函数。需要一个私有构造函数来设置类型为私有内部类的私有字段。 这是鼓励还是劝阻?对于下面列出的场景,还有什么更好的解决方案 请阅读评论,它更加有意义地支持了我的问题。谢谢 public class CopyTree { private TreeNode root; public Copytree() { } // private CopyTree(TreeNode root) { this.root = roo

我遇到了一个场景,我需要一个公共构造函数和一个私有构造函数。需要一个私有构造函数来设置类型为私有内部类的私有字段。 这是鼓励还是劝阻?对于下面列出的场景,还有什么更好的解决方案

请阅读评论,它更加有意义地支持了我的问题。谢谢

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;
}
公共类复制树{
独活根;
公共复制树(){}
//私有复制树(TreeNode根){this.root=root;}
私有静态类树节点{
左树突;
特雷诺德右翼;
整数元素;
TreeNode(TreeNode左、TreeNode右、整数元素){
this.left=左;
这个。右=右;
this.element=元素;
}
}
公共CopyTree CopyTree(){
CopyTree ct=新的CopyTree();
ct.root=copyTree(root);//
类可以同时具有公共构造函数和私有构造函数吗

是的,这是可能的

需要一个私有构造函数来设置类型为私有内部类的私有字段。这是鼓励还是不鼓励

这取决于情况。您是否希望其他类初始化对象的状态。在这里,我认为您创建了CopyTree类以返回Tree的副本,这是一个私有类。因此TreeNode类将被封装,因此您可以选择使用私有构造函数捕获习惯用法

对于下面列出的场景,什么是更好的解决方案

在我看来,私有构造函数捕获习惯用法是更好的解决方案

有关更多信息:

你可以搜索

解决方案53中给出了一个示例:

难题53:做你自己的事

现在轮到您编写一些代码了。假设您有一个名为Thing的库类,其唯一构造函数采用int参数:

Thing实例无法获取其构造函数参数的值。因为Thing是一个库类,所以您无法访问其内部,也无法修改它。 假设您想编写一个名为MyThing的子类,其构造函数通过调用SomeOtherClass.func()方法来计算超类构造函数的参数。此方法返回的值在不同的调用之间发生不可预测的变化。最后,假设您希望将传递给超类构造函数的值存储在子类的最终实例字段中以供将来使用。这是您自然编写的代码:

不幸的是,它是不合法的。如果您尝试编译它,您将收到一条类似以下内容的错误消息:

MyThing.java:
  can't reference arg before supertype constructor has been called
        super(arg = SomeOtherClass.func());
                 ^
如何重写MyThing以达到预期效果?MyThing()构造函数必须是线程安全的:多个线程可以同时调用它

解决方案53:做你自己的事

您可以尝试将调用的结果隐藏在SomeOtherClass.func()中在调用Thing构造函数之前,在静态字段中。此解决方案可行,但很难实现。为了实现线程安全,必须同步对隐藏值的访问,这需要进行无法想象的扭曲。使用线程本地静态字段(java.util.ThreadLocal)可以避免某些扭曲,但存在一个更好的解决方案。 首选的解决方案本质上是线程安全且优雅的。它涉及到在虚构中使用第二个私有构造函数:

此解决方案使用备用构造函数调用。此功能允许类中的一个构造函数链接到同一类中的另一个构造函数。在本例中,MyThing()链接到私有构造函数MyThing(int),它执行所需的实例初始化。在私有构造函数中,表达式SomeOtherClass.func()的值已在参数i中捕获,并可在超类构造函数返回后存储在最终字段param中


可以防止类被其调用方使用Private进行显式实例化 构造器

如果私有构造函数很有用

  • 仅包含静态实用程序方法的类
  • 仅包含常量的类
  • 类型安全枚举
  • 单身汉
它们被证明是不利因素(不限于以下几点。列表可能会增加)

  • 不能创建没有公共或受保护构造函数的类 子类
  • 它们不容易与其他静态方法区分开来

只能按以下方式使用私有构造函数和公共构造函数。但不能对无参数构造函数或同一参数类型同时使用私有构造函数和公共构造函数

public class MyClass {
private MyClass(){

}
public MyClass(int i){

}
}

从您注释掉的代码判断,您已经尝试过了,并且它起到了作用。因此,我只能确认您的发现:是的,私有构造函数可以与公共构造函数共存,是的,这似乎是一个更好的解决方案,因为在接收到对新对象的引用之前,需要进行更多的初始化。

检查此项:
MyThing.java:
  can't reference arg before supertype constructor has been called
        super(arg = SomeOtherClass.func());
                 ^
public class MyThing extends Thing {
    private final int arg;

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

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

}
public MyClass(int i){

}
}