Может ли класс есть как государственные, так и частные конструктор?
Да, это возможно.
Частный конструктор необходим для установки частного поля, тип которого является частным внутренним классом. Это поощряется или обескураживается?
Это зависит от ситуации. Хотите ли вы, чтобы другой класс инициализировал состояние вашего объекта или нет. Здесь я думаю, что вы создали класс CopyTree, чтобы вернуть копию дерева, которая является частным классом. Таким образом, класс TreeNode будет инкапсулирован, поэтому он оставляет вам возможность использовать личную идентификацию захвата конструктора.
Что такое лучшее решение для сценария, перечисленного ниже?
На мой взгляд, индивидуальный идентификатор захвата конструктора является лучшим решением.
Для получения дополнительной информации:
можно искать private constructor capture idiom.
Пример приведен в растворе 53 Java Puzzlers:
Puzzle 53: сделать вещь
Теперь ваша очередь, чтобы написать код. Предположим, что у вас есть библиотека классов называется вещь, единственным конструктор принимает параметр Int:
public class Thing {
public Thing(int i) { ... }
...
}
Вещь экземпляр не обеспечивает способ получить значение своего параметра конструктора. Поскольку Thing является классом библиотеки, у вас нет доступа к его внутренним компонентам, и вы не можете его модифицировать. Предположим, что вы хотите написать подкласс MyThing с конструктором, который вычисляет этот параметр в конструкторе суперкласса, вызывая метод SomeOtherClass.func(). Значение, возвращаемое этим методом, непредсказуемо изменяется от вызова к вызову. Наконец, предположим, что вы хотите сохранить значение, которое было передано конструктору суперкласса в поле конечного экземпляра подкласса для будущего использования. Это код, который вы бы естественно написать:
public class MyThing extends Thing {
private final int arg;
public MyThing() {
super(arg = 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:
public class MyThing extends Thing {
private final int arg;
public MyThing() {
this(SomeOtherClass.func());
}
private MyThing(int i) {
super(i);
arg = i;
}
}
Это решение использует альтернативный конструктор вызова. Эта функция позволяет одному конструктору в классе подключиться к другому конструктору в том же классе. В этом случае MyThing() связывается с частным конструктором MyThing (int), который выполняет инициализацию требуемого экземпляра. Внутри частного конструктора значение выражения SomeOtherClass.func() было зафиксировано в параметре i и может быть сохранено в последнем полевом параметре после возврата конструктора суперкласса.
Проверьте это: http://stackoverflow.com/a/11360712/1544069 – ritesh
Почему вы не принимаете ответ? Они все не спешили отвечать на ваш пост, так что это было бы наименьшее, что вы могли бы сделать взамен. C'mon;) – Andy
Несомненно, мои извинения. Будем в курсе и благодарны всему сообществу за помощь, Также спасибо за то, что обратили на это внимание. – JavaDeveloper