Saklamaksızın yeni nesneler oluşturmak kötü bir uygulama mıdır?


23

Java kodunda yaratılmış nesneleri, nesneye bir referans kaydetmeden gördüm. Örneğin, bir eclipse eklentisinde şöyle bir SWT Kabuğu gördüm:

new Shell();

Bu yeni Shell nesnesi değişkende saklanmaz, ancak pencere kapatıldığında varsayılan olarak [[inanıyorum mu?] Olur.

Onlara bir referans kaydetmeden böyle nesneler oluşturmak kötü bir uygulama mıdır? Yoksa kütüphane kötü bir şekilde mi tasarlandı? Ya bir referansa ihtiyacım yoksa, ancak nesnenin sadece "yan etkilerini" istiyorsam? Yine de referans saklamalı mıyım?

GÜNCELLEŞTİRME:

İtiraf etmek gerekirse, yukarıdaki örneğim zayıf. Bunun gibi yaratılmış UI öğelerini görmeme rağmen, bunun gibi bir SWT Kabuğu oluşturmak büyük olasılıkla anlamsız olacaktır, çünkü Shell örneğinde açık yöntemi çağırmanız gerekir. Java eşzamanlılık eğitiminde aşağıdakiler gibi aix tarafından sağlanan daha iyi örnekler vardır :

(new HelloThread()).start();

Bu uygulama birçok bağlamda görülmektedir, bu yüzden sorular devam etmektedir. İyi bir uygulama mı?


2
Referansı saklamanın amacı ne olurdu?
Daniel R Hicks,

(Muhtemelen bir görüş kavramsal açıdan gibi statik bir yöntem olması, daha iyi olurdu Shell.createTopLevelShell()ya da her türlü, bu durumda bir yapılandırıcı kullanmak vs Ama işlevsel küçük bir fark var..)
Daniel R Hicks

Bu soru, bunlara atıfta bulunmadan nesne oluşturma pratiği, bu pratiği gerektiren sınıflar oluşturma hakkında mı, yoksa özellikle SWT'nin bu tür bir kalıp kullanmasıyla mı ilgili?
StriplingWarrior

1
SWT nesneleri dispose()d olmalıdır : Kural 1: Eğer oluşturduysanız, onu atarsınız. eclipse.org/articles/swt-design-2/swt-design-2.html
jbindel

2
Hata ayıklama amacıyla bir referans tutmak için bir değişken kullanırdım. Bu yöntemde bir kırılma noktanız varsa, nesneyi yerel değişkenle sorgulaması için hata ayıklayıcısını alabilirsiniz. Referans olmadan bunun mümkün, ancak muhtemelen çok daha zor olduğundan eminim.
Martin York

Yanıtlar:


12

Kişisel tercihin bir unsuru var, ancak referansı saklamamanın mutlaka kötü bir uygulama olmadığını düşünüyorum.

Aşağıdaki varsayımsal örneği ele alalım:

new SingleFileProcessor().process(file);

Her dosya için yeni bir işlemci nesnesi oluşturulması gerekiyorsa ve process()çağrıdan sonra gerekmiyorsa , ona bir referans kaydetmenin bir anlamı yoktur.

İşte Java eşzamanlılık eğitiminden alınan başka bir örnek :

(new HelloThread()).start();

Referans saklanmadığında ve gözlerim için gayet iyi okuyan başka örnekler gördüm:

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

( StringBuilderNesne tutulmaz.)

Common.lang's HashCodeBuilderve ark.


2
@BalusC: Saygılarımla, onu neyin balıklaştırdığını ve hangi şekilde bir fabrika yönteminin daha iyi olduğunu göremiyorum (Örneğinizin benimkine benzer olduğunu ve getInstance()bir fabrika olduğunu ve bir singleton olmadığını varsayıyorum ).
NPE

Bir singleton kullanıp kullanmamak fabrikaya kalmış. Fabrikanın arayanı fazla düşünmemeli.
Donal Fellows

Örneğinizde, ifade tamamlandıktan sonra FileProcessor örneğine (muhtemelen) ihtiyaç duyulmaz, oysa OP'nin örneğinde Shell örneği başka bir nesne tarafından başvurulan (kapakların altındadır) ve bu başvuru (ve dolayısıyla Shell nesnesi) sürenin ötesinde devam eder. ifadenin süresi.
Daniel R Hicks,

@BalusC: FileProcessor davranışını değiştirmek için ek yöntemler olabilir process.
Kevin Cline

7

Eğer yoksa ihtiyaç oluşturulan nesneye bir başvuru, daha sonra referans tutunmaya yoktur. Bu kadar basit.


5

Genel olarak, referansları makul bir şekilde yayınlanabilecekleri kadar hızlı bir şekilde yayınlamak iyi bir uygulamadır. Arada bir fark görmüyorum:

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

ve

(new HelloThread()).start();

Kod söz konusu olduğunda, yalnızca olumlu bir şey olabilecek değişken bir ad kullanmaktan kaçınıyorsunuz. JIT derleyicisi, son kullanımdan sonra ipliğin toplanabileceğini anlayabilecek kadar akıllıdır, bu nedenle performans açısından muhtemelen bir fark yoktur.

Kaçınılması gereken tek gerçek sorun , Yapıcı Karşıtı Modeldeki Kod'dur , ancak sorduğun şey bu gibi gelmiyor.


3

SWT kullanıyorsanız, bu kötü olabilir çünkü kendinizden sonra temizlemeniz gerekir (dispose () yöntemini çağırın). Ancak diğer sınıflar için (SWT hariç) sorun yok.

İşte İşletim Sistemi Kaynaklarını Yönetme hakkında bir makale


Dairesel referanslar, nesnelerin Java'da toplanmasını engellemez. Herhangi bir modern Java VM, nesnelerin erişilebilir olup olmadığına bağlı olarak GCable olup olmadığını belirler ve referans sayımı kullanmaz.
jbindel

2
Aslında referans sayımı kullanmaz. Ancak SWT dispose () işlevini çağırmamız gereken özel bir durum olsa da, önce herhangi bir retain () yöntemini çağırmaya gerek yoktur.
Alex

Sadece SWT olmayan duruma atıfta bulunmak istedim.
jbindel

İşte İşletim Sistemi Kaynaklarını Yönetme hakkında bir makale eclipse.org/articles/swt-design-2/swt-design-2.html
Alex

2
Bu durumda yanıltıcı olduğu için “GC'ye imkansız” ifadesini kaldırmak için cevabınızı düzenleyin.
Donal Fellows

1

Her şeyden önce, Java'dan önce C veya C ++ öğrenenleri kızdıracaksınız. Bunu okuyucunun bir profesyonel mi yoksa bir mahkum mu olduğuna karar vermesi için bir alıştırma olarak bırakacağım.

Kesinlikle nesnelerin çok kısa ömürlü olacak şekilde tasarlandığı durumlar olsa da, çoğu zaman bir şey için bir nesneyi oluşturmak için yeterince karmaşıksa, başvuruyu sürdürmek için iyi nedenlere sahip olmak, bu nedenle de bunu saklamamaktır. Bir şey kaçırdıysanız en azından iki kez kontrol etmek için bir uyarı olabilir.

Örneğin, bir öğreticide hiç kimse bir iplik referansı tutmayı umursamıyor, ama gerçek hayatta, bir iş parçacığı oluşturmak istediğiniz kadar uzun sürerse, iş parçacığını iptal etmek istediğiniz kadar uzun sürer. Veya daha kısa ömürlü ise, genellikle joindevam etmeden önce isteyeceğiniz bir sürü ipliği yumurtlarsınız . Veya iş parçacığı oluşturma işleminizin gerçekten başarılı olduğundan emin olmak istersiniz. Veya çıkmadan önce ipliğin temiz bir şekilde bitmesini sağlamak istersiniz. Resmi aldın.


2
Diğer dillerden rahatsız edici programcılar için endişe gerçekten ilk endişe mi?
Buttons840,

Ekibinizin yapısına bağlı olarak okunabilirlik / aşinalık / stil sorunu haline getirir, çünkü birçok insanın taşıdığı bir stildir. C ++ 'da hiç programlanmayan insanlar bile çoğu zaman yapan akıl hocalarından stiller alırlar.
Karl Bielefeldt
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.