2013-07-08 3 views
6

Я столкнулся с сценарием, где мне нужен публичный и частный конструктор. Для создания частного поля, тип которого является частным внутренним классом, необходим частный конструктор. Является ли это защищенным или обескураженным? Иначе, что является лучшим решением для сценария, перечисленного ниже?Может ли класс иметь открытый и закрытый конструктор?

Прочтите комментарий, который более подробно поддерживает мой вопрос. Спасибо,

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; 
} 
+2

Проверьте это: http://stackoverflow.com/a/11360712/1544069 – ritesh

+1

Почему вы не принимаете ответ? Они все не спешили отвечать на ваш пост, так что это было бы наименьшее, что вы могли бы сделать взамен. C'mon;) – Andy

+1

Несомненно, мои извинения. Будем в курсе и благодарны всему сообществу за помощь, Также спасибо за то, что обратили на это внимание. – JavaDeveloper

ответ

0

Может ли класс есть как государственные, так и частные конструктор?

Да, это возможно.

Частный конструктор необходим для установки частного поля, тип которого является частным внутренним классом. Это поощряется или обескураживается?

Это зависит от ситуации. Хотите ли вы, чтобы другой класс инициализировал состояние вашего объекта или нет. Здесь я думаю, что вы создали класс 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 и может быть сохранено в последнем полевом параметре после возврата конструктора суперкласса.

0

Класс может быть исключен из экспликаций, созданных его вызывающими пользователями, используя приватные конструкторы .

Где частные Конструкторы полезны,

  • классы, содержащие только статические служебные методы
  • классы, содержащие только константы
  • типобезопасен Перечисления
  • Singletons

Где они оказываются (не ограничиваясь ниже). Список может расти)

  • Классы без общественных или защищенных конструкторов не могут быть подклассами.
  • Они не могут быть легко различимы с другими статическими методами.
0

Вы можете использовать как частный, так и открытый конструктор только следующим образом. Но вы не можете использовать оба параметра без конструктора аргументов или одного типа аргументов.

public class MyClass { 
private MyClass(){ 

} 
public MyClass(int i){ 

} 
} 
0

Судя по вашему прокомментированному коду, вы уже пробовали его, и это сработало. Поэтому я могу только подтвердить ваш вывод: да, частный конструктор может сосуществовать с общедоступным, и да, это похоже на лучшее решение, так как больше инициализации выполняется до получения ссылки на новый объект.

Смежные вопросы