Дополнительно
Должен ли я инстанцировать переменные экземпляра при объявлении или в конструкторе?
Есть ли преимущества у того или иного подхода?
Пример 1:
class A {
B b = new B();
}
Пример 2:
class A {
B b;
A() {
b = new B();
}
}
217
15
{ а = новый(); }
Проверьте в <а href="и http://java.sun.com/docs/books/tutorial/java/javaOO/initial.html">солнце'объяснение и советы</а>
От в <а href="и http://docstore.mik.ua/orelly/java-ent/jnut/ch03_02.htm" и GT;учебник</а>:
Кроме того, вы, возможно, захотите, чтобы lazily initialize своей области. В случаях, когда инициализация поля является дорогостоящей операцией, вы можете инициализировать его, как только это необходимо:
И в конечном итоге (как указал Билл), ради управления зависимостями, лучше avoid с помощью оператора
new
в любом месте в пределах своего класса. Вместо этого, с использованием <а href="и http://en.wikipedia.org/wiki/Dependency_injection">внедрения зависимостей</а> предпочтительнее - т. е. позволить кому-нибудь другому (другой класс/Основы) создания и внедрения зависимостей в вашем классе.Другим вариантом было бы использовать инъекция зависимостей.
Это снимает ответственность за создание объекта
Б
из конструктора "а". Это сделает ваш код более проверяемым и легче поддерживать в долгосрочной перспективе. Идея в том, чтобы уменьшить сцепление между двумя классами " а " и "Б". Благо, что это дает вам, что теперь вы можете передать любой объект, который расширяетБ
(или реализует "Б", если он является интерфейсом) вA
's в конструктор и он будет работать. Одним недостатком является то, что вы даете инкапсуляцию объектаБ
, поэтому он подвержен абонентома
конструктор. Вы'll должны рассмотреть, если выгоды стоит это компромисс, но во многих случаях они.Я погорел в интересной форме сегодня:
Видите ошибку? Получается, что инициализаторе
А = нуль
вызывается после конструктор суперкласса вызывается. Поскольку конструктор суперкласса вызывает init(), инициализация а затем кА = нуль
инициализации.мое личное и"правило" и (редко сломанный) - это:
Так что я бы код, как:
Этот путь я всегда 100% уверен, где искать переменные (в начале блока), и их назначения (как только это имеет смысл после провозглашения). Это ветры потенциально является более эффективным, поскольку вы никогда не инициализировать переменную со значением, которое не используется (например объявить и init vars и затем бросать исключение, прежде чем половина этих Варс необходимо иметь значение). Вы также не ветер делает бессмысленным инициализации (вроде int я = 0; и потом, прежде чем"Я " и; используется, Я = 5;.
Я ценю постоянство очень много, так что после этого на "правило" это то, чем я занимаюсь все время, и это делает его гораздо легче работать с кодом, так как вы не'т придется охотиться вокруг, чтобы найти вещи.
Ваш пробег может варьироваться.
Пример 2 является менее гибким. Если вы добавить еще один конструктор, вы должны помнить, чтобы инстанцировать области, а также в том, что конструктор. Просто инстанцировать поля непосредственно, или ввести где-то ленивая загрузка в геттер.
Если инстанцирование требует больше, чем просто "новое", использовать инициализатор блок. Это будет работать вне зависимости от используемого конструктора. Е. Г.
Я воспринимаю это почти просто дело вкуса, покуда инициализация простой и не'т необходимости каких-либо логике.
Конструктор подход немного более хрупким, если вы не'т использовать инициализатор блок, потому что если вы позже добавить второй конструктор и забудьте инициализировать б здесь, вы'будете получать нуль только при использовании, что в прошлом конструктор.
См http://java.sun.com/docs/books/tutorial/java/javaOO/initial.html для получения более подробной информации об инициализации в Java (и за разъяснения по initalizer блоки и другие не известные функции инициализации).
Используя либо инъекции зависимостей или отложенная инициализация всегда предпочтительнее, так как уже подробно об этом в другой ответы.
Когда вы Don'т хотите или можете'т использовать эти образцы, а для примитивных типов данных, есть три веские причины, что я могу думать, почему это'ов предпочтительнее, чтобы инициализировать атрибуты класса вне конструктора:
Оба метода допустимы. Обратите внимание, что в последнем случае
b=new B()
может не инициализироваться, если присутствует другой конструктор. Считайте, что код инициализатора вне конструктора является общим конструктором и код выполняется.Я думаю, что пример 2 предпочтительнее. Я думаю, что лучшей практикой является объявление вне конструктора и инициализация в конструкторе.
Я'вэ не видел следующие ответы:
Возможное преимущество инициализация в момент объявления может быть с в настоящее время язь's, где вы можете очень легко перейти к объявлению переменной (в основном
Сочетание клавиш Ctrl-<hover_over_the_variable и GT;-<left_mouse_click>
) из любого места в коде. Вы тогда сразу увидите значение этой переменной. В противном случае, у вас есть, чтобы "Поиск" и на том месте, где инициализация делается (в основном:) конструктор.Это преимущество является, конечно, общее для всех других логических рассуждений, но для некоторых людей, что "функция" и может быть более важным.
Есть еще один тонкий повод, чтобы инициализировать вне конструктора, который никто не упомянул раньше (очень специфические, надо сказать). Если вы используете для создания инструментов UML диаграммы классов из кода (обратный инжиниринг), большинство инструментов я считаю отмечу инициализации примере 1, и перенести его на схему (если вы предпочитаете, чтобы она показала начальные значения, как я делаю). Они не будут принимать эти начальные значения из примера 2. Опять же, это очень специфическая причина - если вы работаете с UML инструменты, но как только я узнал, что, я пытаюсь принять все по умолчанию значения вне конструктора, если, как было сказано раньше, возникает вопрос о возможных исключений или сложная логика.
Второй вариант предпочтительней, так как позволяет использовать различную логику в конструкторы для создания экземпляра класса и использовать конструкторы сцепления. Е. Г.
Так что второго варианта является более гибким.
В связи с вышесказанным
нуль инит можно было бы избежать, т. к. все равно это'ы по умолчанию. Однако, если нужно другое значение по умолчанию, затем, из-за неконтролируемого порядок инициализации, Я бы исправить следующим образом:
Это'ы довольно разные на самом деле:
Декларация происходит до начала строительства. Так сказать, если кто инициализировал переменную (B в данном случае) как на места, конструктор'ы инициализации заменит на уровне класса.
Так объявлять переменные на уровне класса, инициализировать их в конструкторе.
Второй - пример ленивой инициализации. Первый - более простая инициализация, но по сути они одинаковы.