Jav*_*per 6 java private public
我遇到了一个场景,我需要一个公共和私有构造函数.需要私有构造函数来设置其类型为私有内部类的私有字段.这是囤积还是气馁?那么对于下面列出的场景,什么是更好的解决方案?
请阅读评论,这更有意义地支持我的问题.谢谢,
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;
}
Run Code Online (Sandbox Code Playgroud)
一个类可以同时具有公共和私有构造函数吗?
对的,这是可能的。
需要一个私有构造函数来设置类型为私有内部类的私有字段。这是鼓励还是劝阻?
这取决于实际情况。是否希望其他类初始化您的对象的状态。在这里,我认为您已经创建了 CopyTree 类来返回 Tree 的副本,这是一个私有类。因此 TreeNode 类将被封装,因此它让您可以选择使用私有构造函数捕获惯用法。
对于下面列出的场景,什么是更好的解决方案?
在我看来,私有构造函数捕获惯用法是更好的解决方案。
了解更多信息:
您可以搜索private constructor capture idiom。
Java Puzzlers的解决方案 53 中给出了一个例子:
谜题 53:做你的事
现在轮到你编写一些代码了。假设您有一个名为 Thing 的库类,其唯一的构造函数采用 int 参数:
public class Thing {
public Thing(int i) { ... }
...
}
Run Code Online (Sandbox Code Playgroud)
Thing 实例无法获取其构造函数参数的值。因为 Thing 是一个库类,所以您无法访问其内部,也无法修改它。假设您要编写一个名为 MyThing 的子类,其构造函数通过调用方法 SomeOtherClass.func() 来计算超类构造函数的参数。此方法返回的值在每次调用时都会发生不可预测的变化。最后,假设您希望将传递给超类构造函数的值存储在子类的最终实例字段中以供将来使用。这是您自然会编写的代码:
public class MyThing extends Thing {
private final int arg;
public MyThing() {
super(arg = SomeOtherClass.func());
...
}
...
}
Run Code Online (Sandbox Code Playgroud)
不幸的是,这是不合法的。如果您尝试编译它,您将收到类似于以下内容的错误消息:
MyThing.java:
can't reference arg before supertype constructor has been called
super(arg = SomeOtherClass.func());
^
Run Code Online (Sandbox Code Playgroud)
如何重写MyThing才能达到预期的效果?MyThing() 构造函数必须是线程安全的:多个线程可以同时调用它。
解决方案 53:做你的事
您可以尝试在调用 Thing 构造函数之前将调用 SomeOtherClass.func() 的结果存储在静态字段中。这个解决方案是可行的,但很尴尬。为了实现线程安全,您必须同步对隐藏值的访问,这需要难以想象的扭曲。其中一些扭曲可以通过使用线程本地静态字段 (java.util.ThreadLocal) 来避免,但存在更好的解决方案。首选解决方案本质上是线程安全且优雅的。它涉及在 MyThing 中使用第二个私有构造函数:
public class MyThing extends Thing {
private final int arg;
public MyThing() {
this(SomeOtherClass.func());
}
private MyThing(int i) {
super(i);
arg = i;
}
}
Run Code Online (Sandbox Code Playgroud)
此解决方案使用备用构造函数调用。此功能允许类中的一个构造函数链接到同一类中的另一个构造函数。在本例中,MyThing() 链接到私有构造函数 MyThing(int),后者执行所需的实例初始化。在私有构造函数中,表达式 SomeOtherClass.func() 的值已被捕获在参数 i 中,并且可以在超类构造函数返回后存储在最终字段 param 中。
| 归档时间: |
|
| 查看次数: |
4505 次 |
| 最近记录: |