Normalde new
anahtar kelime kullanarak nesneler oluştururuz , örneğin:
Object obj = new Object();
Dizeler nesnelerdir, ancak new
onları oluşturmak için kullanmıyoruz :
String str = "Hello World";
Bu neden? İle String yapabilir miyim new
?
Normalde new
anahtar kelime kullanarak nesneler oluştururuz , örneğin:
Object obj = new Object();
Dizeler nesnelerdir, ancak new
onları oluşturmak için kullanmıyoruz :
String str = "Hello World";
Bu neden? İle String yapabilir miyim new
?
new String(...)
geniş dizeleri substringing zaman bir uygulama detay atlatmak için kullanılmıştır. Bu Java 7'de düzeltildi ve artık gerekli değil.
Yanıtlar:
Önceden söylenenlere ek olarak , Java'daki String değişmezleri [yani, benzer "abcd"
ancak benzemeyen dizeler new String("abcd")
] dahil edilir - bu, "abcd" den her söz ettiğinizde String
, yeni bir örnek yerine tek bir örneğe bir referans alacağınız anlamına gelir. her seferinde. Yani sahip olacaksınız:
String a = "abcd";
String b = "abcd";
a == b; //True
ama olsaydı
String a = new String("abcd");
String b = new String("abcd");
o zaman sahip olmak mümkün
a == b; // False
(ve herhangi birinin hatırlatmaya ihtiyacı olması durumunda, her zaman .equals()
Dizeleri karşılaştırmak için kullanın ; ==
fiziksel eşitlik testleri).
Interning String değişmez değerleri iyidir çünkü bunlar genellikle birden fazla kez kullanılır. Örneğin, (yapmacık) kodu düşünün:
for (int i = 0; i < 10; i++) {
System.out.println("Next iteration");
}
Dizelerin interneti olmasaydı, "Sonraki yineleme" nin 10 kez somutlaştırılması gerekirdi, oysa şimdi yalnızca bir kez somutlaştırılacak.
Dizeler Java'da "özel" nesnelerdir. Java tasarımcıları, Dizelerin o kadar sık kullanıldığına akıllıca karar verdiler ve kendi sözdizimlerine ve bir önbelleğe alma stratejisine ihtiyaçları vardı. Bir dizeyi şunu söyleyerek bildirdiğinizde:
String myString = "something";
myString, "bir şey" değerine sahip String nesnesine bir referanstır. Daha sonra beyan ederseniz:
String myOtherString = "something";
Java, myString ve myOtherString'in aynı olduğunu anlayacak kadar akıllıdır ve bunları aynı nesne olarak global bir String tablosunda saklayacaktır. Bunu yapmak için Dizeleri değiştiremeyeceğiniz gerçeğine dayanır. Bu, gerekli bellek miktarını azaltır ve karşılaştırmaları daha hızlı yapabilir.
Onun yerine yazarsan
String myOtherString = new String("something");
Java, myString nesnesinden farklı olarak sizin için yepyeni bir nesne yaratacaktır.
String a = "abc"; // 1 Object: "abc" added to pool
String b = "abc"; // 0 Object: because it is already in the pool
String c = new String("abc"); // 1 Object
String d = new String("def"); // 1 Object + "def" is added to the Pool
String e = d.intern(); // (e==d) is "false" because e refers to the String in pool
String f = e.intern(); // (f==e) is "true"
//Total Objects: 4 ("abc", c, d, "def").
Umarım bu birkaç şüpheyi ortadan kaldırır. :)
Bu bir kısayol. Başlangıçta böyle değildi, ama Java onu değiştirdi.
Bu SSS kısaca bundan bahsediyor. Java Spesifikasyon kılavuzu da bundan bahsediyor. Ama internette bulamıyorum.
String, birkaç optimizasyona tabidir (daha iyi bir ifade istemek için). String'in ayrıca diğer nesnelerin aksine operatör aşırı yüklemesine (+ operatörü için) sahip olduğunu unutmayın. Yani bu çok özel bir durum.
Gereksiz nesneler oluşturmaktan kaçınmak için genellikle String değişmezlerini kullanırız. String nesnesini oluşturmak için new operatörü kullanırsak, her seferinde yeni bir nesne oluşturacaktır.
Misal:
String s1=“Hello“;
String s2=“Hello“;
String s3= new String(“Hello“);
String s4= new String(“Hello“);
Hafızadaki yukarıdaki kod için:
Java'da Dizeler, yalnızca Dizeler için geçerli olan birçok kurala sahip özel bir durumdur. Çift tırnak, derleyicinin bir String nesnesi oluşturmasına neden olur. String nesneleri değişmez olduğundan, bu, derleyicinin birden çok dizeyi staj yapmasına ve daha büyük bir dize havuzu oluşturmasına izin verir. İki özdeş String sabiti her zaman aynı nesne referansına sahip olacaktır. Durumun böyle olmasını istemiyorsanız, yeni String ("") kullanabilirsiniz ve bu, çalışma zamanında bir String nesnesi oluşturur. İntern () yöntemi eskiden dinamik olarak oluşturulan dizelerin dize arama tablosuna göre kontrol edilmesine neden olmak için yaygındı. Bir dizede bir dizeye dahil edildikten sonra, nesne referansı standart String örneğini gösterecektir.
String a = "foo";
String b = "foo";
System.out.println(a == b); // true
String c = new String(a);
System.out.println(a == c); // false
c = c.intern();
System.out.println(a == c); // true
Sınıf yükleyici bir sınıfı yüklediğinde, tüm String sabitleri String havuzuna eklenir.
Sözdizimsel şeker.
String s = new String("ABC");
sözdizimi hala mevcuttur.
String small = new String(huge.substring(int, int));
büyük temelleri geri dönüştürmenize olanak tanır . char[]
huge
Hala kullanabilirsiniz new String("string")
, ancak dizge değişmezleri olmadan yeni dizeler oluşturmak daha zor olacaktır ... karakter dizileri veya baytlar kullanmanız gerekir :-) Dize değişmezleri bir ek özelliğe sahiptir: herhangi bir sınıf noktasından aynı dizeye kadar tüm aynı dize değişmezleri örnek (staj yapıyorlar).
Değişmez (tırnak işaretlerindeki karakterler), host sınıfı yüklendiğinde zaten oluşturulmuş bir String nesnesi olduğundan, yeni bir dizeye neredeyse hiç gerek yoktur. Bir literal ve don üzerinde metotları çağırmak tamamen yasaldır, ana ayrım, literallerin sağladığı kolaylıktır. Bir dizi karakter oluşturup, karakterle doldurup yeni bir String (karakter dizisi) yapmamız gerekirse, bu büyük bir acı ve kayıp olur.
İle yeni bir String oluşturmaktan çekinmeyin
String s = new String("I'm a new String");
Olağan gösterim s = "new String";
, aşağı yukarı uygun bir kısayoldur - bu , denklem için uygun olan Dizelere gerçekten ihtiyaç duyduğunuz oldukça nadir durumlar dışında performans nedenleriyle kullanılmalıdır.
(string1.equals(string2)) && !(string1 == string2)
DÜZENLE
Yorum yanıt olarak: Bu edilmiş değil o, Kendisine teze bir tavsiye ama sadece bir tek bir doğrudan yanıt olması amaçlanmıştır biz 'yeni' anahtar kelimesini kullanmayın basitçe doğru değildir Strings için. Umarım bu düzenleme (yukarıdakiler dahil) bunu biraz açıklığa kavuşturur. BTW - SO ile ilgili yukarıdaki soruya birkaç iyi ve çok daha iyi cevap var.
new String(...)
Uygulamanız farklı bir kimliğe sahip bir Dize oluşturmanızı GEREKTİRMEZSE , kullanmakta "kendinizi özgür hissetmemelisiniz" .
Değişmez havuz, anahtar kelime kullanılmadan oluşturulmuş tüm Dizeleri içerir new
.
Bir fark var: Yeni referansı olmayan dize, String değişmez havuzunda saklanır ve yeni ile String, yığın belleğinde olduklarını söyler.
Yeni ile dizgi, tıpkı diğer nesneler gibi bellekte başka yerdedir.
Çünkü String, java'da değişmez bir sınıftır.
Şimdi neden değişmez? String değişmez olduğundan, birden fazla evre arasında paylaşılabilir ve String işlemini harici olarak senkronize etmemize gerek yoktur. As String, sınıf yükleme mekanizmasında da kullanılır. Yani String değiştirilebilir olsaydı java.io.writer abc.xyz.mywriter olarak değiştirilebilirdi
TString obj1 = new TString("Jan Peter");
TString obj2 = new TString("Jan Peter");
if (obj1.Name == obj2.Name)
System.out.println("True");
else
System.out.println("False");
Çıktı:
Doğru
İki ayrı nesne oluşturdum, her ikisinin de bir alanı (ref) 'Ad' var. Yani bu durumda bile "Jan Peter" paylaşılıyor, java'nın nasıl işlediğini anlıyorsam ..
StringPool, javada Hashmap kullanılarak gerçeklenir. Her zaman yeni bir anahtar kelimeyle oluşturuyorsak, String Pool'da arama yapmaz ve onun için yeni bir hafıza yaratırsak, bu daha sonra ihtiyaç duyulabilir, eğer bellek yoğun bir işlemimiz varsa ve performansı etkileyecek tüm dizeleri yeni anahtar kelimeyle oluşturuyorsak uygulamamızın. Bu nedenle, dizge oluşturmak için yeni anahtar sözcükler kullanmamanız tavsiye edilir, çünkü o zaman yalnızca Dize havuzuna gidecek ve bu da bir Hashmap olacaktır, (bellek kaydedildi, yeni anahtar sözcükle oluşturulmuş çok sayıda dizgimiz olup olmadığını düşünün) burada saklanacak ve dizge zaten mevcutsa başvurusu (genellikle Yığın belleğinde bulunur) yeni oluşturulan dizeye döndürülür. Yani performansı artırmak için yapılır.