Вопрос о том, что означает «длинный», неясен. Вот несколько возможных интерпретаций:
Интерпретация # 1: у конструктора много параметров
Конструкторы с множеством параметров могут привести к плохой читаемости, и существуют лучшие альтернативы.
Вот цитата из Effective Java 2nd Edition, Item 2: Рассмотрим шаблон компоновщика, когда сталкиваемся со многими параметрами конструктора :
Традиционно программисты использовали шаблон телескопического конструктора , в котором вы предоставляете конструктору только необходимые параметры, другой - с одним необязательным параметром, третий - с двумя дополнительными параметрами и т. Д. .
Шаблон телескопического конструктора выглядит примерно так:
public class Telescope {
final String name;
final int levels;
final boolean isAdjustable;
public Telescope(String name) {
this(name, 5);
}
public Telescope(String name, int levels) {
this(name, levels, false);
}
public Telescope(String name, int levels, boolean isAdjustable) {
this.name = name;
this.levels = levels;
this.isAdjustable = isAdjustable;
}
}
И теперь вы можете делать любое из следующего:
new Telescope("X/1999");
new Telescope("X/1999", 13);
new Telescope("X/1999", 13, true);
В настоящее время вы не можете, однако, установить только name
и isAdjustable
и оставить levels
по умолчанию. Вы можете обеспечить больше перегрузок конструктора, но очевидно, что число будет взорваться при увеличении количества параметров, и у вас может даже быть несколько аргументов boolean
и int
, которые действительно могут создать беспорядок.
Как вы можете видеть, это не очень приятный для написания шаблон, и даже менее приятный в использовании (что здесь означает "правда"? Что такое 13?).
Bloch рекомендует использовать шаблон построителя, который позволит вам написать что-то вроде этого:
Telescope telly = new Telescope.Builder("X/1999").setAdjustable(true).build();
Обратите внимание, что теперь параметры названы, и вы можете устанавливать их в любом порядке, в котором вы хотите, и вы можете пропустить те, которые вы хотите оставить со значениями по умолчанию. Это, конечно, намного лучше, чем телескопические конструкторы, особенно когда существует огромное количество параметров, которые принадлежат многим из тех же типов.
Смотри также
Похожие вопросы
Интерпретация # 2: конструктор выполняет большую работу, которая стоит времени
Если работа должна выполняться во время построения, то выполнение ее в конструкторе или вспомогательном методе на самом деле не имеет большого значения. Однако, когда конструктор делегирует работу вспомогательному методу, убедитесь, что он не может быть переопределен, поскольку это может привести к множеству проблем.
Вот некоторая цитата из Effective Java 2nd Edition, Item 17: Разработка и документация для наследования, или же запретить его :
Есть еще несколько ограничений, которым должен подчиняться класс, чтобы разрешить наследование. Конструкторы не должны вызывать переопределяемые методы , прямо или косвенно. Если вы нарушите это правило, произойдет сбой программы. Конструктор суперкласса выполняется перед конструктором подкласса, поэтому метод переопределения в подклассе будет вызван до запуска конструктора подкласса. Если переопределяющий метод зависит от какой-либо инициализации, выполняемой конструктором подкласса, метод не будет работать должным образом.
Вот пример для иллюстрации:
public class ConstructorCallsOverride {
public static void main(String[] args) {
abstract class Base {
Base() { overrideMe(); }
abstract void overrideMe();
}
class Child extends Base {
final int x;
Child(int x) { this.x = x; }
@Override void overrideMe() {
System.out.println(x);
}
}
new Child(42); // prints "0"
}
}
Здесь, когда конструктор Base
вызывает overrideMe
, Child
не завершил инициализацию final int x
, и метод получает неправильное значение. Это почти наверняка приведет к ошибкам и ошибкам.
Интерпретация # 3: конструктор выполняет большую часть работы, которую можно отложить
Построение объекта может быть сделано быстрее, когда некоторая работа откладывается до того момента, когда это действительно необходимо; это называется ленивая инициализация . Например, когда создается String
, он фактически не вычисляет свой хэш-код. Он делает это только тогда, когда сначала требуется хеш-код, а затем кэширует его (поскольку строки неизменны, это значение не изменится).
Однако рассмотрим Effective Java 2nd Edition, Item 71: Используйте ленивую инициализацию разумно . Ленивая инициализация может привести к незначительным ошибкам, и не всегда дает улучшенную производительность, которая оправдывает добавленную сложность. Не преждевременно оптимизировать.