String bir sınıfken Java'da neden + operatörüyle Dizeler ekleyebiliyorsunuz? Kodda String.java
bu operatör için herhangi bir uygulama bulamadım. Bu kavram nesne yönelimini ihlal ediyor mu?
String bir sınıfken Java'da neden + operatörüyle Dizeler ekleyebiliyorsunuz? Kodda String.java
bu operatör için herhangi bir uygulama bulamadım. Bu kavram nesne yönelimini ihlal ediyor mu?
Yanıtlar:
Java'da aşağıdaki basit ifadelere bakalım
int x=15;
String temp="x = "+x;
Derleyici dahili "x = "+x;
olarak bir türe dönüştürür ve tamsayıyı dizeye "eklemek" için StringBuilder
kullanır .append(int)
.
Herhangi bir tür, dize dönüşümüyle Dize türüne dönüştürülebilir.
İlkel tip T'nin bir x değeri, uygun bir sınıf örneği oluşturma ifadesine (§15.9) bağımsız değişken olarak verilerek önce bir referans değerine dönüştürülür:
- T boole ise, yeni Boole (x) kullanın.
- T bir karakter ise, yeni Karakter (x) kullanın.
- T bayt, kısa veya int ise, yeni Tamsayı (x) kullanın.
- T uzunsa, yeni Long (x) kullanın.
- T float ise, yeni Float (x) kullanın.
- T çift ise, yeni Double (x) kullanın.
Bu referans değeri daha sonra dize dönüşümüyle String türüne dönüştürülür.
Şimdi sadece referans değerlerin dikkate alınması gerekiyor:
- Başvuru boş ise, "null" dizesine dönüştürülür (dört ASCII karakteri n, u, l, l).
- Aksi takdirde, dönüştürme, başvurulan nesnenin toString yönteminin argümansız olarak çağrılmasıyla gerçekleştirilir; ancak toString yöntemini çağırmanın sonucu null ise, bunun yerine "null" dizesi kullanılır.
ToString yöntemi, ilkel sınıf Object (§4.3.2) tarafından tanımlanır. Boolean, Character, Integer, Long, Float, Double ve String gibi birçok sınıf bunu geçersiz kılar.
Dizi dönüştürme bağlamının ayrıntıları için §5.4'e bakın.
Dize Birleştirme Optimizasyonu: Bir uygulama, bir ara String nesnesi oluşturmaktan ve sonra atmaktan kaçınmak için tek adımda dönüştürme ve birleştirme yapmayı seçebilir. Yinelenen dize birleştirme performansını artırmak için, bir Java derleyicisi, bir ifadenin değerlendirilmesiyle oluşturulan ara String nesnelerinin sayısını azaltmak için StringBuffer sınıfını veya benzer bir tekniği kullanabilir.
İlkel türler için, bir uygulama, doğrudan bir ilkel türden bir dizeye dönüştürerek bir sarıcı nesnenin yaratılmasını optimize edebilir.
Optimize edilmiş sürüm aslında önce tam sarılmış bir Dize dönüşümü yapmayacaktır.
Bu, derleyici tarafından kullanılan en iyi duruma getirilmiş sürümün iyi bir örneğidir, ancak bir ilkel dönüştürülmeden derleyicinin şeyleri arka planda bir StringBuilder'a dönüştürdüğünü görebilirsiniz:
http://caprazzi.net/posts/java-bytecode-string-concatenation-and-stringbuilder/
Bu java kodu:
public static void main(String[] args) {
String cip = "cip";
String ciop = "ciop";
String plus = cip + ciop;
String build = new StringBuilder(cip).append(ciop).toString();
}
Bunu üretir - iki birleştirme stilinin nasıl aynı bayt koduna yol açtığını görün:
L0
LINENUMBER 23 L0
LDC "cip"
ASTORE 1
L1
LINENUMBER 24 L1
LDC "ciop"
ASTORE 2
// cip + ciop
L2
LINENUMBER 25 L2
NEW java/lang/StringBuilder
DUP
ALOAD 1
INVOKESTATIC java/lang/String.valueOf(Ljava/lang/Object;)Ljava/lang/String;
INVOKESPECIAL java/lang/StringBuilder.<init>(Ljava/lang/String;)V
ALOAD 2
INVOKEVIRTUAL java/lang/StringBuilder.append(Ljava/lang/String;)Ljava/lang/StringBuilder;
INVOKEVIRTUAL java/lang/StringBuilder.toString()Ljava/lang/String;
ASTORE 3
// new StringBuilder(cip).append(ciop).toString()
L3
LINENUMBER 26 L3
NEW java/lang/StringBuilder
DUP
ALOAD 1
INVOKESPECIAL java/lang/StringBuilder.<init>(Ljava/lang/String;)V
ALOAD 2
INVOKEVIRTUAL java/lang/StringBuilder.append(Ljava/lang/String;)Ljava/lang/StringBuilder;
INVOKEVIRTUAL java/lang/StringBuilder.toString()Ljava/lang/String;
ASTORE 4
L4
LINENUMBER 27 L4
RETURN
Yukarıdaki örneğe ve verilen örnekteki kaynak koduna dayalı bayt kodunun nasıl oluşturulduğuna bakıldığında, derleyicinin aşağıdaki ifadeyi dahili olarak dönüştürdüğünü fark edebileceksiniz.
cip+ciop;
içine
new StringBuilder(cip).append(ciop).toString();
Başka bir deyişle, +
dizge birleştirme işlemindeki operatör , daha ayrıntılı StringBuilder
deyim için etkili bir kısaltmadır .
+
Operatörün işlenenlerini kontrol eden Java derleyici özelliğidir . Ve işlenenlere göre bayt kodunu üretir:
Java spesifikasyonunun söylediği şu :
+ Ve
-
operatörlerine eklemeli operatörler denir. AdditiveExpression: MultiplicativeExpression AdditiveExpression + MultiplicativeExpression AdditiveExpression - MultiplicativeExpressionKatkı operatörleri aynı önceliğe sahiptir ve sözdizimsel olarak sol ilişkilidir (soldan sağa gruplanırlar). Bir
+
operatörün işlenenlerinden birinin türü iseString
, işlem dize birleştirme işlemidir.Aksi takdirde,
+
operatörün işlenenlerinden her birinin türü, ilkel bir sayısal türe dönüştürülebilir (§5.1.8) bir tür olmalıdır, yoksa bir derleme zamanı hatası oluşur.Her durumda, ikili
-
operatörün işlenenlerinden her birinin türü, ilkel bir sayısal türe dönüştürülebilir (§5.1.8) bir tür olmalıdır, yoksa bir derleme zamanı hatası oluşur.
String sınıfı + operatörünü nasıl geçersiz kılar?
Öyle değil. Derleyici yapar. Kesin olarak, derleyici String işlenenleri için + operatörünü aşırı yükler .
Öncelikle (+) aşırı yüklenmiştir, geçersiz kılınmamıştır
Java dili, Java Strings nesneleri için aşırı yüklenmiş olan dizi birleştirme operatörü (+) için özel destek sağlar.
Sol taraftaki işlenen String ise birleştirme olarak çalışır.
Sol taraftaki işlenen Tamsayı ise toplama operatörü olarak çalışır
int
ve bu durumda normal Java kuralları uygulanır.
Java dili, dizgi birleştirme operatörü (+) ve diğer nesnelerin dizelere dönüştürülmesi için özel destek sağlar. Dize birleştirme, StringBuilder
(veya StringBuffer
) sınıfı ve append
yöntemi aracılığıyla uygulanır .
+
Operatörün uygulandığında anlamı, String
herkesin zaten yazdığı gibi, dil tarafından tanımlanır. Bunu yeterince ikna edici bulmadığınız için şunu düşünün:
İnts, float ve double'ların hepsi farklı ikili temsillere sahiptir ve bu nedenle iki tamsayı eklemek, bit manipülasyonu açısından iki kayan nokta eklemekten farklı bir işlemdir: İnts için parça parça ekleyebilir, biraz taşıyabilir ve taşmayı kontrol edebilirsiniz; float'lar için mantisler ve üslerle ayrı ayrı ilgilenmelisiniz.
Bu nedenle, prensip olarak, "ekleme", "eklenen" nesnelerin doğasına bağlıdır. Java bunu Dizeler için olduğu kadar ints ve float'lar için de tanımlar (longs, double, ...)
+
Operatör genellikle ile değiştirilir StringBuilder
derleme sırasında. Konuyla ilgili daha fazla ayrıntı için bu yanıtı kontrol edin .
+
Operatörün değiştirmediği durumlar var StringBuilder
mı?
+
) operatörü Java'nın dil özelliğidir.