Arka fon
Finalin Java'da gösterilebileceği üç yer vardır:
Bir dersi final yapmak, sınıfın tüm alt sınıflarını engeller. Bir yöntemin sonlandırılması, yöntemin alt sınıflarının onu geçersiz kılmasını önler. Bir alanı final yapmak daha sonra değiştirilmesini önler.
yanılgılar
Nihai yöntemler ve alanlar etrafında gerçekleşen optimizasyonlar vardır.
Son bir yöntem, HotSpot'un satır içi ile optimize etmesini kolaylaştırır. Bununla birlikte, HotSpot bunu, aksi ispatlanana kadar geçersiz kılınmadığı varsayımı üzerinde çalıştığı için yöntem kesin olmasa bile yapar. SO hakkında bu konuda daha fazla bilgi
Son bir değişken agresif bir şekilde optimize edilebilir ve bununla ilgili daha fazla bilgi JLS bölümünde 17.5.3 okunabilir .
Ancak, bu anlayışla , bu optimizasyonların hiçbirinin bir sınıfı final yapmakla ilgili olmadığının farkında olunmalıdır . Bir sınıfı final yaparak performans kazancı yoktur.
Bir sınıfın son yönünün değişmezlikle hiçbir ilgisi yoktur. Biri nihai olmayan değişmez bir sınıfa ( BigInteger gibi ) veya değişebilir ve nihai bir sınıfa ( StringBuilder gibi ) sahip olabilir. Bir sınıf ise yaklaşık karar olmalıdır nihai olması tasarımın bir sorudur.
Son tasarım
Dizeler en çok kullanılan veri türlerinden biridir. Haritaların anahtarları olarak bulunurlar, kullanıcı adlarını ve şifreleri saklarlar, klavyeden veya web sayfasındaki bir alandan okuduğunuz şeydir. Dizeler her yerde .
Haritalar
String'i alt sınıflara ayırabiliyorsanız ne olacağını düşünmeniz gereken ilk şey, birisinin başka bir şekilde bir String gibi görünen mutable bir String sınıfı oluşturabileceğini fark etmektir. Bu, Haritalar'ı her yerde karıştırır.
Bu varsayımsal kodu düşünün:
Map t = new TreeMap<String, Integer>();
Map h = new HashMap<String, Integer>();
MyString one = new MyString("one");
MyString two = new MyString("two");
t.put(one, 1); h.put(one, 1);
t.put(two, 2); h.put(two, 2);
one.prepend("z");
Bu, genel olarak bir Harita ile değiştirilebilir bir anahtar kullanmakla ilgili bir sorun, ancak oraya ulaşmaya çalıştığım şey, aniden Harita kırılmasıyla ilgili bir dizi şey. Giriş artık haritada doğru noktada değil. Bir HashMap'te, karma değeri değişti (olması gerekir) ve bu nedenle artık doğru girişte değil. TreeMap'te, düğümlerden biri yanlış tarafta olduğundan ağaç şimdi kesildi.
Bu anahtarlar için bir Dize kullanımı çok yaygın olduğundan, Dize'nin sonlandırılmasıyla bu davranış önlenmelidir.
Eğer String neden Java ile değişmez?Dizelerin değişmez doğası hakkında daha fazla bilgi için.
Hain teller
Dizeler için çeşitli hain seçenekler vardır. Eşit çağrıldığında her zaman true döndüren bir String yaptım ve bir şifre kontrolüne geçip geçmediğimi düşünün. Veya MyString'e yapılan atamaların Dize'nin bir kopyasını bazı e-posta adreslerine göndermesini sağladı mı?
String'i alt sınıflandırma yeteneğiniz olduğunda bunlar çok gerçek olasılıklardır.
Java.lang Dize optimizasyonları
Daha önce bahsetmişken bu final String'i daha hızlı yapmaz. Bununla birlikte, String sınıfı (ve içindeki diğer sınıflar java.lang
), diğer java.lang
sınıfların String için genel API'yi kullanmak yerine dahili sınıflarla uğraşmasını sağlamak için alanların ve yöntemlerin paket düzeyinde korumasını sık sık kullanır . Menzil denetimi olmayan getChars veya StringBuffer veya yapıcı tarafından kullanılan lastIndexOf gibi işlevler temel diziyi paylaşan (bellek sorunları nedeniyle değiştirilen bir Java 6 şeyi olduğunu unutmayın).
Birisi String'in bir alt sınıfını yaptıysa, bu optimizasyonları paylaşamazdı (eğer bir parçası olmadıkça java.lang
, ama bu kapalı bir paket) ).
Uzatma için bir şeyler tasarlamak daha zor
Genişletilebilir bir şey tasarlamak zor . Bu, başka bir şeyin değiştirilebilmesi için iç kısımlarınızın bölümlerini açığa çıkarmanız gerektiği anlamına gelir.
Genişletilebilir bir Dizede bellek sızıntısı düzeltilemedi. Bu kısımlarının alt sınıflara maruz kalması ve bu kodun değiştirilmesi, alt sınıfların kırılacağı anlamına gelecektir.
Java, geriye dönük uyumlulukla gurur duyuyor ve çekirdek sınıfları uzantıya açarak, üçüncü taraf alt sınıflarıyla hesaplanabilirliği korurken, bazı şeyleri düzeltme yeteneğini kaybediyor.
Checkstyle , "DesignForExtension" adı verilen ve her sınıfın şunlardan birini uygulayan bir kurala sahiptir (iç kodu yazarken beni gerçekten sinirlendirir):
Rasyonel olan:
Bu API tasarım stili, üst sınıfları alt sınıfların kırılmasına karşı korur. Dezavantajı, alt sınıfların esnekliklerinde sınırlı olmalarıdır, özellikle de kodun üst sınıfta yürütülmesini engelleyemezler, ancak bu aynı zamanda alt sınıfların süper yöntemi çağırmayı unutarak üst sınıfın durumunu bozamayacağı anlamına gelir.
Uygulama sınıflarının genişletilmesine izin vermek, alt sınıfların dayandığı sınıfın durumunu bozabileceği ve üst sınıfın verdiği çeşitli garantilerin geçersiz olacağı anlamına gelebilir. String olarak kompleks olarak bir şey için, bu bir kesinlik neredeyse olduğunu bunun değişen parçası olacak şeyler bölünürler.
Geliştirici hurbis
Bir geliştirici olmanın bir parçası. Her geliştiricinin içinde kendi araçları koleksiyonu ile kendi String alt sınıflarını oluşturma olasılığını göz önünde bulundurun . Fakat şimdi bu alt sınıflar birbirlerine serbestçe atanamazlar.
WleaoString foo = new WleaoString("foo");
MichaelTString bar = foo; // This doesn't work.
Bu şekilde deliliğe yol açar. Her yerde String'e yayınlama ve String'in sizin için bir örnek olup olmadığını kontrol etme hayır, sadece ... onunla dayalı yeni dize yapma ve, String sınıfı ya da değil. Yapma.
Bence iyi Dize sınıf yazmak ... ama C ++ yazmak bu çılgın insanlara birden dize uygulamaları yazma ayrılıp uğraşmak zorunda eminim std::string
ve char*
artırmak ve gelen ve bir şey SString ve geri kalan tüm .
Java String sihri
Java'nın Dizelerle yaptığı birkaç sihirli şey var. Bunlar, bir programcının başa çıkmasını kolaylaştırır, ancak dilde bazı tutarsızlıklar ortaya çıkarır. String'de alt sınıflara izin vermek, bu büyülü şeylerle nasıl başa çıkılacağı hakkında çok önemli düşünceler alacaktı:
Dize Değişmezleri (JLS 3.10.5 )
Birinin yapmasına izin veren kod olması:
String foo = "foo";
Bu, Tamsayı gibi sayısal türlerin boksuyla karıştırılmamalıdır. Yapamazsın 1.toString()
ama yapabilirsin "foo".concat(bar)
.
+
Operatör (JLS 15.18.1 )
Java'da başka hiçbir başvuru türü üzerinde bir işleç kullanılmasına izin vermez. Dize özeldir. Dize birleştirme operatörü de derleyici düzeyinde çalışır, böylece çalışma zamanında değil derlendiğinde "foo" + "bar"
olur "foobar"
.
Dize Dönüştürme (JLS 5.1.11 )
Tüm nesneler yalnızca bir String bağlamında kullanılarak Dizelere dönüştürülebilir.
Dize Stajyerliği ( JavaDoc )
String sınıfı, String değişmezleriyle derleme türünde doldurulan nesnenin kurallı temsillerine sahip olmasına izin veren Dizeler havuzuna erişebilir.
String'in bir alt sınıfına izin vermek, String'i programlamayı kolaylaştıran bu bitlerin, diğer String türleri mümkün olduğunda yapılması çok zor veya imkansız hale geleceği anlamına gelir.