Apakah praktik yang buruk untuk membuat objek baru tanpa menyimpannya?

23

Saya telah melihat objek yang dibuat dalam kode Java tanpa menyimpan referensi ke objek. Misalnya, dalam plugin gerhana saya telah melihat Shell SWT dibuat seperti:

new Shell();

Objek Shell baru ini tidak disimpan dalam variabel, tetapi akan tetap direferensikan sampai jendela dibuang yang [saya percaya?] Terjadi secara default ketika jendela ditutup.

Apakah praktik yang buruk untuk membuat objek seperti ini tanpa menyimpan referensi kepada mereka? Atau perpustakaan itu dirancang dengan buruk? Bagaimana jika saya tidak memerlukan referensi, tetapi hanya menginginkan "efek samping" dari objek? Haruskah saya menyimpan referensi?

MEMPERBARUI:

Diakui, contoh saya di atas buruk. Walaupun saya telah melihat elemen UI dibuat seperti ini, membuat SWT Shell seperti ini mungkin tidak ada gunanya karena Anda perlu memanggil metode terbuka pada instance Shell. Ada contoh yang lebih baik yang disediakan oleh aix seperti berikut dari tutorial concurrency Java :

(new HelloThread()).start();

Praktek ini terlihat dalam banyak konteks, jadi pertanyaannya tetap. Apakah ini praktik yang baik?

Buttons840
sumber
2
Apa gunanya menyimpan referensi?
Daniel R Hicks
(Mungkin akan lebih baik, dari sudut pandang konseptual, untuk memiliki metode statis seperti Shell.createTopLevelShell()atau apa pun, vs menggunakan konstruktor dalam kasus ini. Tetapi secara fungsional ada sedikit perbedaan.)
Daniel R Hicks
Apakah pertanyaan ini tentang praktik membuat objek tanpa merujuknya, membuat kelas yang memerlukan praktik ini, atau apakah ini khusus tentang cara SWT menggunakan pola semacam ini?
StriplingWarrior
1
Objek SWT harus dispose()d: Aturan 1: Jika Anda membuatnya, Anda membuangnya. eclipse.org/articles/swt-design-2/swt-design-2.html
jbindel
2
Saya akan menggunakan variabel untuk menyimpan referensi untuk keperluan debugging. Jika Anda memiliki break point dalam metode ini maka Anda bisa mendapatkan debugger untuk menanyakan objek melalui variabel lokal. Tanpa referensi saya yakin itu mungkin tapi mungkin jauh lebih sulit.
Martin York

Jawaban:

12

Ada elemen preferensi pribadi untuk ini, tapi saya pikir tidak menyimpan referensi tidak selalu merupakan praktik yang buruk.

Pertimbangkan contoh hipotetis berikut:

new SingleFileProcessor().process(file);

Jika objek prosesor baru perlu dibuat untuk setiap file, dan tidak diperlukan setelah process()panggilan, tidak ada gunanya menyimpan referensi untuk itu.

Berikut adalah contoh lain, diambil dari tutorial concurrency Java :

(new HelloThread()).start();

Saya telah melihat banyak contoh lain ketika referensi tidak disimpan, dan itu terbaca dengan baik di mata saya, seperti:

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

( StringBuilderObjek tidak disimpan.)

Ada pola serupa yang melibatkan common.lang's HashCodeBuilderet al.

NPE
sumber
2
@ BalusC: Dengan hormat, saya tidak melihat apa yang membuatnya mencurigakan dan dengan cara apa memiliki metode pabrik lebih baik (saya menganggap contoh Anda analog dengan milik saya, dan getInstance()merupakan pabrik dan bukan singleton).
NPE
Terserah pabrik apakah akan menggunakan singleton atau tidak. Penelepon pabrik tidak boleh terlalu memikirkannya.
Donal Fellows
Dalam contoh Anda contoh FileProcessor (mungkin) tidak diperlukan setelah pernyataan selesai, sedangkan dalam contoh OP contoh Shell adalah (di bawah penutup) direferensikan oleh objek lain, dan referensi itu (dan karenanya objek Shell) bertahan di luar durasi pernyataan.
Daniel R Hicks
@ BalusC: FileProcessor dapat memiliki metode tambahan untuk mengubah perilaku process.
kevin cline
7

Jika Anda tidak memerlukan referensi ke objek yang dibuat, maka jangan pegang referensi. Sesederhana itu.

Mike Baranczak
sumber
5

Secara umum, praktik yang baik untuk merilis referensi secepat mungkin dapat dirilis. Saya tidak melihat perbedaan antara:

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

dan

(new HelloThread()).start();

Sejauh menyangkut kode, Anda hanya menghindari penggunaan nama variabel, yang bisa menjadi hal yang positif. Kompiler JIT pada umumnya cukup pintar untuk mengenalinya bahwa sampah dapat mengumpulkan utas setelah penggunaan terakhirnya, jadi mungkin tidak ada perbedaan dari sudut pandang kinerja.

Satu-satunya masalah nyata yang harus dihindari adalah Kode dalam Constructor Anti-Pattern , tetapi tidak terdengar seperti itu yang Anda tanyakan.

StriplingWarrior
sumber
3

Ini bisa buruk jika Anda menggunakan SWT, karena di sana Anda harus membersihkan diri sendiri (memanggil metode buang ()). Tetapi untuk kelas lain (non SWT) tidak apa-apa.

Inilah artikel tentang Mengelola Sumber Daya Sistem Operasi

Alex
sumber
Referensi lingkaran tidak mencegah benda menjadi sampah yang dikumpulkan di Jawa. VM Java modern apa pun menentukan apakah objek tersebut GCable berdasarkan pada apakah objek tersebut dapat dijangkau, dan tidak menggunakan penghitungan referensi.
jbindel
2
Memang tidak menggunakan penghitungan referensi. Tetapi SWT adalah kasus khusus di mana kita perlu memanggil dispose (), meskipun tidak perlu memanggil retain () terlebih dahulu.
Alex
Saya bermaksud merujuk hanya pada kasus non-SWT.
jbindel
Berikut ini artikel tentang Mengelola Sumber Daya Sistem Operasi eclipse.org/articles/swt-design-2/swt-design-2.html
Alex
2
Dalam hal ini, edit jawaban Anda untuk menghapus pernyataan tentang "tidak mungkin untuk GC" karena menyesatkan.
Donal Fellows
1

Pertama-tama, Anda akan mengganggu orang yang belajar C atau C ++ sebelum Java. Saya akan meninggalkan itu sebagai latihan bagi pembaca untuk memutuskan apakah itu pro atau kontra.

Walaupun ada beberapa situasi di mana objek dirancang untuk berumur pendek, sebagian besar waktu jika sesuatu cukup kompleks untuk membuat objek, cukup kompleks untuk memiliki alasan yang baik untuk menyimpan referensi, jadi tidak menyimpannya harus di paling tidak menjadi peringatan untuk mengecek apakah Anda melewatkan sesuatu.

Misalnya, dalam tutorial tidak ada yang peduli tentang menjaga referensi utas, tetapi dalam kehidupan nyata, jika sesuatu membutuhkan waktu cukup lama sehingga Anda ingin menelurkan utas, biasanya butuh waktu yang cukup lama sehingga Anda ingin dapat membatalkan utas. Atau jika berumur pendek, Anda biasanya akan memunculkan banyak utas yang Anda inginkan joinsebelum melanjutkan. Atau Anda ingin memastikan kreasi thread Anda benar-benar berhasil. Atau Anda ingin memastikan utas selesai dengan bersih sebelum keluar. Anda mendapatkan fotonya.

Karl Bielefeldt
sumber
2
Apakah mengkhawatirkan programmer yang mengganggu dari bahasa lain benar-benar menjadi perhatian pertama?
Buttons840
Ini membuatnya menjadi masalah keterbacaan / keakraban / gaya tergantung pada komposisi tim Anda, karena itu adalah gaya yang dibawa oleh banyak orang. Bahkan orang yang belum pernah memprogram dalam C ++ sering mengadopsi gaya dari mentor mereka yang melakukannya.
Karl Bielefeldt