Плохо ли создавать новые объекты, не сохраняя их?

23

Я видел объекты, созданные в коде Java без сохранения ссылки на объект. Например, в плагине eclipse я видел SWT Shell, созданный так:

new Shell();

Этот новый объект Shell не сохраняется в переменной, но на него будут ссылаться до тех пор, пока окно не будет удалено, что [по моему мнению?] Происходит по умолчанию при закрытии окна.

Плохо ли создавать подобные объекты, не сохраняя ссылки на них? Или библиотека была плохо спроектирована? Что если мне не нужна ссылка, а нужны только «побочные эффекты» объекта? Должен ли я хранить ссылку в любом случае?

ОБНОВИТЬ:

Надо признать, мой приведенный выше пример плохой. Хотя я видел элементы пользовательского интерфейса, созданные таким образом, создание подобной оболочки SWT, вероятно, было бы бессмысленным, поскольку вам нужно вызывать метод open в экземпляре оболочки. AIX предлагает лучшие примеры, такие как следующие из руководства по параллелизму Java :

(new HelloThread()).start();

Эта практика видна во многих контекстах, поэтому вопросы остаются. Это хорошая практика?

Buttons840
источник
2
Какой смысл хранить ссылку?
Даниэль Р Хикс
(Вероятно, было бы лучше, с концептуальной точки зрения, иметь статический метод, такой как Shell.createTopLevelShell()или любой другой, по сравнению с использованием конструктора в этом случае. Но функционально есть небольшая разница.)
Даниэль Р Хикс
Является ли этот вопрос практикой создания объектов без ссылки на них, создания классов, требующих такой практики, или это конкретно вопрос о том, как SWT использует этот тип шаблона?
StriplingWarrior
1
Объекты SWT должны быть dispose()d: Правило 1: Если вы его создали, вы его утилизируете. eclipse.org/articles/swt-design-2/swt-design-2.html
jbindel
2
Я бы использовал переменную для хранения ссылки в целях отладки. Если у вас есть точка останова в этом методе, вы можете получить отладчик для запроса объекта через локальную переменную. Без ссылки я уверен, что это возможно, но, вероятно, намного сложнее.
Мартин Йорк,

Ответы:

12

Есть элемент личного предпочтения этому, но я думаю, что не хранить ссылку не обязательно плохая практика.

Рассмотрим следующий гипотетический пример:

new SingleFileProcessor().process(file);

Если для каждого файла требуется создать новый объект процессора и он не нужен после process()вызова, нет смысла хранить ссылку на него.

Вот еще один пример, взятый из руководства по параллелизму Java :

(new HelloThread()).start();

Я видел много других примеров, когда ссылка не сохранена, и которые читаются мне очень хорошо, например:

String str = new StringBuilder().append(x).append(y).append(z).toString();

( StringBuilderОбъект не сохранился.)

Существуют сходные схемы, связанные с Common.lang HashCodeBuilderи соавт.

NPE
источник
2
@BalusC: С уважением, я не вижу, что делает его сомнительным и каким образом использование фабричного метода лучше (я предполагаю, что ваш пример аналогичен моему и getInstance()является фабричным, а не единичным).
NPE
Зависит от того, использовать ли синглтон или нет. Заказчик фабрики не должен слишком много думать об этом.
Донал Феллоуз
В вашем примере экземпляр FileProcessor (предположительно) не нужен после завершения инструкции, тогда как в примере OP на экземпляр Shell (под прикрытием) ссылается другой объект, и эта ссылка (и, следовательно, объект Shell) сохраняется за пределами длительность заявления.
Даниэль Р Хикс
@BalusC: FileProcessor может иметь дополнительные методы для изменения поведения process.
Кевин Клайн
7

Если вы этого не сделаете нужна ссылка на созданный объект, не держитесь за ссылку. Это так просто.

Майк Баранчак
источник
5

Как правило, рекомендуется выпускать ссылки настолько быстро, насколько это возможно. Я не вижу разницы между:

HelloThread thread = new HelloThread();
thread.start();
// where thread is never used for the rest of the method

а также

(new HelloThread()).start();

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

Единственная реальная проблема, которую следует избегать, это код в конструкторе Anti-Pattern , но это не похоже на то, о чем вы спрашиваете.

StriplingWarrior
источник
3

Это может быть плохо, если вы используете SWT, потому что там вам придется убирать за собой (вызывая метод dispose ()). Но для других классов (не SWT) это нормально.

Вот статья об управлении ресурсами операционной системы

Alex
источник
Циркулярные ссылки не препятствуют сборке мусора в Java. Любая современная Java VM определяет, являются ли объекты GCable, на основе того, достижимы ли они, и не использует подсчет ссылок.
Jbindel
2
На самом деле он не использует подсчет ссылок. Но SWT - это особый случай, когда нам нужно вызвать dispose (), хотя нет необходимости сначала вызывать retain ().
Алекс
Я имел в виду, чтобы ссылаться только на случай без SWT.
Jbindel
Вот статья об управлении ресурсами операционной системы eclipse.org/articles/swt-design-2/swt-design-2.html
Alex
2
В этом случае отредактируйте свой ответ, чтобы удалить утверждение о «невозможности для GC», поскольку оно вводит в заблуждение.
Donal Fellows
1

Прежде всего, вы будете раздражать людей, которые изучили C или C ++ до Java. Я оставлю это как упражнение для читателя, чтобы решить, является ли это за или против.

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

Например, в учебнике никто не заботится о сохранении ссылки на поток, но в реальной жизни, если что-то занимает достаточно много времени, чтобы вы хотели порождать поток, обычно это занимает достаточно много времени, чтобы вы могли иметь возможность отменить поток. Или если вы живете недолго, вы обычно создаете кучу потоков, которые захотите, joinпрежде чем продолжить. Или вы хотите убедиться, что создание вашего потока действительно успешно. Или вы хотите удостовериться, что поток завершается чисто перед выходом. Вы получаете картину.

Карл Билефельдт
источник
2
Является ли беспокойство по поводу раздражающих программистов из других языков первым делом?
Buttons840
Это делает проблему читабельности / знакомства / стиля в зависимости от состава вашей команды, потому что это стиль, который переносят многие люди. Даже люди, которые никогда не программировали на C ++, часто перенимают стили от своих наставников.
Карл Билефельдт