'Nihai' anahtar kelime neden sektörde bu kadar az kullanılıyor? [kapalı]


14

finalBirkaç yıl önce Java'da anahtar kelimenin güçlerini keşfettiğimden, kodlarımı çok daha okunabilir hale getirmeme yardımcı oldu, çünkü insanlar salt okunur değişkenleri kolayca görebiliyor. Ayrıca JIT'e küçük bir destek sağlayabilir ve bu çok sınırlı olsa da, özellikle android platformları gibi gömülü cihazları hedeflerken zarar veremez.

Ancak her şeyden öte, bir tasarımın değişikliklere daha dayanıklı hale getirilmesine ve kod tabanını değiştirmeleri gerektiğinde diğer komisyonculara yol göstermeye katkıda bulunur.

Ancak, bazı JDK kaynak kodunu tararken, sınıflar, yöntemler veya değişkenler için bu anahtar kelimeye hiç rastlamadım. Aynı şey gözden geçirmem gereken çeşitli sistemler için de geçerlidir.

Bir sebebi var mı? Her şeyin içeriden değişmesine izin vermek ortak bir tasarım paradigması mı?


mikro optimizasyonlarda, finalalanların ayarlanması bir volatilealan yazmakla aynı semantiğe sahiptir ve daha sonra bunları okumak için uçucu okuma semantiği olması gerekir, bu her zaman istediğiniz şey değildir
cırcır ucube

5
@ratchet: Sanırım bu daha çok fonksiyonel programlamada olduğu gibi sınıflarınızı değişmez yapmakla ilgili.
Jonas

@Kwebble: Belki daha da önemlisi, bireysel String örnekleri değiştirilemez.
03:11

Yanıtlar:


9

Görmemenizin nedeninin JDK'nın genişletilmek üzere tasarlandığından şüpheleniyorum (tüm programlarınızın üzerine inşa edildiği temeldir). Uygulama kodunun bundan faydalanması hiç de nadir değildir. Ayrıca kütüphane kodunda bir çok görmeyi beklemiyordum (kütüphaneler genellikle uzantı için de tasarlandığından).

Bazı açık kaynak kodlu projelere bir göz atın ve daha fazlasını bulacağınızı düşünüyorum.

Java'da gördüklerinizin aksine, .NET dünyasında, sealedsınıfların varsayılan olarak (bir sınıfa uygulanan final sınavına benzer) ve geliştiricinin açıkça açması gerektiği argümanı birçok kez duydum. o.


2
Hatta nesne değişkenleri "bir kez spawn, asla geçersiz kılma" bazı JDK sınıflarının birçok özel veya korunan üyelerine atıfta bulunuyordu. Özellikle salıncak paketinde. Boş bir işaretçi ile değiştirme, bileşenleri kullanırken hatalara yol açacağından, bunlar 'final' için mükemmel adaylardır.
Aurelien Ribon

1
@ Aurélien: Sizi daha iyi hissettirirse , .NET Framework'teki sınıfların çoğu , çerçeve sınıflarını kendi işlevleriyle genişletmek isteyen bazı kullanıcıların şaşkınlığına karşı mühürlenir . Ancak bu sınırlama, Uzatma Yöntemleri
Robert Harvey

1
Bence bu uzatmadan kaçınmaktan çok değişmezlikle ilgili. Başka bir deyişle finalyöntemlerde değil, on alanlarının kullanımı . Değişmez sınıflar da genişletilecek şekilde tasarlanabilir.
Jonas

15

Bir finalşeyin salt okunur olduğunu iletmekle ilgili sorun, yalnızca int, charvb. Sonuç olarak, finalanahtar kelimeyi bir nesnede kullandığınızda, yalnızca başvurunun salt okunur olduğunu, nesnenin kendisinin hala değiştirilebilir olduğunu söylüyorsunuz .

Nesneyi salt okunur yaparsa daha fazla kullanılmış olabilir. C ++ 'da tam olarak constbunu yapan ve sonuç olarak çok daha kullanışlı ve yoğun bir şekilde kullanılan bir anahtar kelime.

finalAnahtar kelimeyi yoğun bir şekilde kullandığım bir yer , bu tür şeyler tarafından oluşturulan karışıklığı önlemek için parametrelerle:

public void someMethod(FancyObject myObject) {
    myObject = new FancyObject();
    myObject.setProperty(7);
}
...
public static void main(final String[] args) {
    ...
    FancyObject myObject = new FancyObject();
    someOtherObject.someMethod(myObject);
    myObject.getProperty(); // Not 7!
}

Bu örnekte, bunun neden işe yaramadığı açıktır, ancak eğer someMethod(FancyObject)büyük ve karmaşık bir karışıklık ortaya çıkabilir. Neden bundan kaçınmıyorsunuz?

Ayrıca Sun (veya şimdi sanırım Oracle) kodlama standartlarının bir parçası.


1
finalJava API sınıflarında daha fazla kullanım varsa , çoğu nesne birçok Scala kütüphanesinde olduğu gibi değişmezdi. Daha sonra nesne alanları finalyapmak, sınıfı birçok durumda değiştirilemez hale getirir. Bu tasarım zaten BigDecimalve String.
Jonas

@Jonas Schmmd'nin cevabında "insanlar salt okunur değişkenlerin neler olduğunu kolayca görebildiğinden" dediğinden ve buna göre cevap verdiğinden beri soruyu 4. nokta hakkında daha fazla okumak için okudum. Belki de bu varsayımı cevaba eklemeliydim.
Gyan aka Gary Buyn

Parametreyi yeniden atamak istediğiniz zaman olduğunu unutmayın. Örneğin bir dize parametresini kırpmaktır.
Steve Kuo

@Steve Genellikle bu durumda atanacak yeni bir değişken oluştururum.
Gyan aka Gary Buyn

1
@Gary, en azından benim için, hataların / karışıklığın bir parametreyi yeniden ataması nedeniyle çok nadirdir. Daha çok dağınık serbest kod var ve bir hataya neden olan bir parametreyi yeniden atama şansını kabul ediyorum. Kod yazarken / değiştirirken dikkatli olun.
Steve Kuo

4

finalAnahtar kelimenin okunabilirliği artırdığını kabul ediyorum . Bir nesnenin değişmez olduğunu anlamayı kolaylaştırır. Bununla birlikte, Java'da özellikle parametrelerde kullanıldığında (bence) son derece ayrıntılıdır. Bu, insanların bunu kullanmaması gerektiği anlamına gelmez, çünkü ayrıntılıdır, daha ziyade ayrıntılı olduğu için kullanmazlar.

Scala gibi başka bir dil, son bildirimleri ( val ) yapmayı çok daha kolay hale getirir . Bu dillerde, nihai bildirimler değişkenlerden daha yaygın olabilir.

Son anahtar kelimenin birçok farklı kullanımının olduğunu unutmayın. Yayınınız çoğunlukla 2 ve 3 numaralı öğeleri kapsar.

  1. Final Sınıfları (JLS 8.1.1.2)
  2. final Sahaları (JLS 8.3.1.2)
  3. Nihai Yöntemler (JLS 8.4.3.3)
  4. Nihai Değişkenler (JLS 4.12.4)

2

İlk olarak, resmi Java Kod Sözleşmeleri , belirli bir kullanımı ne lehte ne de yasaklar final. Yani, JDK geliştiricileri tercih ettikleri yolu seçmekte özgürdürler.

Akıllarını okuyamıyorum ama bana göre, kullanılıp kullanılmayacağına dair tercih finalodak noktasıydı. Kod üzerinde yoğunlaşmak için yeterli zamanım olup olmadığı meselesi .

  • Diyelim ki, projelerimden birinde, 100 kod satırı gibi bir günde ortalama harcama yapabiliriz . Bu projede, finalkodda zaten yeterince açık bir şekilde ifade edilen şeyleri gizleyen bir çöp olarak farklı bir algım vardı. JDK geliştiricileri de bu kategoriye giriyor.
     
    Öte yandan, 100 kod satırında bir saat ortalaması geçirdiğimiz başka bir projede tamamen zıttı . Orada, kendimi finalve diğerinin kodunda bir makineli tüfek gibi ateş ettiğimi buldum - çünkü bunu benden önce yazan adamın niyetini tespit etmenin en hızlı yolu ve benzer şekilde kendi niyetimi iletmenin en hızlı yolu daha sonra kodum üzerinde çalışacak adam.

Ayrıca JIT'e küçük bir destek sağlayabilir ve bu çok sınırlı olsa da,

Yukarıdaki gibi akıl yürütmek kaygandır. Erken optimizasyon zarar verebilir; Donald Knuth, "tüm kötülüklerin kökü" olarak adlandırdığı kadar ileri gider . Seni tuzağa düşürmesine izin verme. Aptal kod yaz .


2

Son zamanlarda Eclipse IDE'de "Eylemleri Kaydet" özelliğinin sevincini keşfettim. Kodumu yeniden biçimlendirmeye, eksik @Overrideek açıklamalar eklemeye ve ifadelerde gereksiz parantezleri kaldırmaya veya finalher vurduğumda otomatik olarak her yere anahtar kelime koymaya zorlanıyorum ctrl + S. Bu tetikleyicilerin bazılarını etkinleştirdim ve oğlum, çok yardımcı oluyor!

Bu tetikleyicilerin çoğunun kodum için hızlı bir akıl sağlığı kontrolü gibi davrandığı ortaya çıktı.

  • Bir yöntemi geçersiz kılmak istedim ama vurduğumda ek açıklama görünmedi ctrl + smi? - belki bir yerde parametre tiplerini berbat ettim!
  • Bazı parantez kaydetme kodundan kaldırıldı? - belki de bir mantık ifadesinin bir programcının çabucak dolaşması çok zordur. Aksi halde, neden bu parantezi ilk etapta ekleyeyim?
  • Bu parametre veya yerel değişken değil final. O mu var değerini değiştirmek için?

Daha az değişken, hata ayıklama zamanında daha az sorun değiştirdiği ortaya çıktı. Kaç kez bir değişkenin değerini sadece bir şekilde 5'ten 7'ye değiştiğini bulmak için takip ediyordunuz? "Nasıl olabilir ?!" kendinize sorun ve mantığınızda bir hata yaptığınızı öğrenmek için sayısız yönteme adım atarak birkaç saat geçirin. Ve düzeltmek için bir bayrak daha, birkaç koşul eklemeniz ve burada ve orada bazı değerleri dikkatlice değiştirmeniz gerekir.

Hata ayıklamaktan nefret ediyorum! Hata ayıklayıcıyı her çalıştırdığımda zamanımın tükendiğini hissediyorum ve umutsuzca çocukluk hayallerimin en azından bazılarının gerçek olmasını sağlamak için o zamana ihtiyacım var ! Hata ayıklama ile cehenneme! finaldemek ki artık gizemli değer değişiklikleri yok. Daha fazla finals => benim kod daha az dayanıksız parçaları => daha az hata => iyi şeyler yapmak için daha fazla zaman!

finalSınıflara ve yöntemlere gelince gerçekten umrumda değil. Ben polimorfizmi seviyorum. Polimorfizm yeniden kullanım anlamına gelir, daha az kod daha az hata anlamına gelir. JVM, yine de sanallaştırma ve yöntem inlining ile oldukça iyi bir iş yapıyor, bu yüzden sağlam olmayan performans avantajları için kodun yeniden kullanılması için olasılıkları öldürmede bir değer görmüyorum.


Koddaki tüm bu finalkodları görmek başlangıçta biraz dikkat dağıtıcıdır ve alışması da zaman alır. Bazı takım arkadaşlarım hala çok fazla finalanahtar kelime görmek için çok şaşırıyor . Keşke IDE'de özel sözdizimi renklendirmesi için bir ayar olsaydı. Kod okurken çok dikkat dağıtıcı olmayacak şekilde gri tonlarına (ek açıklamalar gibi) geçmek için mutlu olurum. Eclipse şu anda returnve diğer tüm anahtar kelimeler için ayrı bir renge sahiptir, ancak bunun için ayrı değildir final.


1
Belki de OCaml veya F # gibi fonksiyonel dillere bakmayı düşünebilirsiniz. Bu diller çok daha az hata ayıklama gerektirir, bunun nedenlerinden biri her şeyin varsayılan olarak salt okunur olmasıdır. Basitçe, bir kez atandığında, işlevsel bir dilde bir değişken değişmez.
Abel

1
Evet, biliyorum ve aslında zaman zaman bazı ML kodları yazıyorum - ilham kaynağımın olduğu yer burası :) Bu, kullandığınız dil değil, uyguladığınız ilkeler ve teknikler hakkında. Bir Haskell ve tüm zorunluluk gidebilir dogösterimde :) Sure Java işlevsel bir tarzda yazmaya ama en azından size sağlam kod -ve yazmasına olanak tanır için en iyi dil değil o 's Gerçekten önemli olan konuları.
Andrew Андрей Листочкин
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.