Orijinal: “ ” və ya Konstruktordan istifadə edərək Java sətri yaradın? X Wang tərəfindən Java-da sətir iki üsuldan istifadə etməklə yaradıla bilər:
String x = "abc";
String y = new String("abc");
Qoşa dırnaq işarələrindən istifadə etmək və konstruktordan istifadə etmək arasında fərq nədir?
1. Qoşa Sitatlar vs. Konstruktor
Bu suala iki sadə misala baxmaqla cavab vermək olar. Misal 1:String a = "abcd";
String b = "abcd";
System.out.println(a == b); // True
System.out.println(a.equals(b)); // True
a==b
doğrudur, çünki onların a
hər ikisi b
eyni obyektə - metod sahəsində hərfi (aşağıda hərfi sətir) elan edilmiş sətirə istinad edir (biz oxucunu resursumuzdakı mənbəyə istinad edirik: Java dilini anlamaq üçün ən yaxşı 8 diaqram , diaqram 8). Eyni sətir hərfi bir dəfədən çox yaradıldıqda, sətrin yalnız bir nüsxəsi yaddaşda saxlanılır, onun yalnız bir nümunəsi (bizim vəziyyətimizdə "abcd"). Buna "string interning" deyilir. Kompilyasiya zamanı emal edilən bütün sətir sabitləri avtomatik olaraq Java-da interned olunur. Misal 2:
String c = new String("abcd");
String d = new String("abcd");
System.out.println(c == d); // False
System.out.println(c.equals(d)); // True
c==d
false çünki c
onlar d
yaddaşda (yığında) iki fərqli obyektə istinad edir. Fərqli obyektlər həmişə fərqli istinadlara malikdir. Bu diaqram yuxarıda təsvir olunan iki vəziyyəti göstərir:
2. Proqramın icra mərhələsində sətirlərin interninq edilməsi
Müəllif LukasEder-ə təşəkkür edir (aşağıdakı şərh onundur): String interning də proqramın icrası zamanı baş verə bilər, hətta konstruktorlardan istifadə edərək iki sətir yaradılsa belə:String c = new String("abcd").intern();
String d = new String("abcd").intern();
System.out.println(c == d); // Now true
System.out.println(c.equals(d)); // True
3. Qoşa dırnaq işarələri və konstruktorlardan nə vaxt istifadə etməli
Hərfi "abcd" həmişə String tipli olduğuna görə konstruktordan istifadə etmək əlavə lazımsız obyekt yaradacaq. Beləliklə, yalnız bir sətir yaratmaq lazımdırsa, ikiqat dırnaq işarələrindən istifadə edilməlidir. Əgər yığında həqiqətən yeni bir obyekt yaratmalısınızsa, konstruktordan istifadə etməlisiniz. İstifadə halları burada göstərilmişdir (orijinal) . (Tərcümə edilmiş mətni aşağıda təqdim edirəm. Amma yenə də bu linkdə şərhçilərin kodu ilə tanış olmağı tövsiyə edirəm.)JDK 6 və JDK 7-də substring() metodu
JDK 6 və JDK 7-də substring() metodu By X Wang JDK 6 və JDK 7-də metodsubstring(int beginIndex, int endIndex)
fərqlidir. Bu fərqləri bilmək bu metoddan daha yaxşı istifadə etməyə kömək edə bilər. Oxumağın asanlığı üçün aşağıda substring()
tam sintaksisi nəzərdə tutacağıq, yəni. substring(int beginIndex, int endIndex)
.
1. Substring() nə edir?
Metod simvol nömrəsi ilə başlayan və simvol nömrəsi ilə bitənsubstring(int beginIndex, int endIndex)
sətri qaytarır . beginIndex
endIndex-1
String x = "abcdef";
x = x.substring(1,3);
System.out.println(x);
Çıxış:
bc
2. Substring() çağırılanda nə baş verir?
Bilə bilərsiniz ki, dəyişməzliyə görəx
, x nəticəsini təyin edərkən x.substring(1,3)
, x
tamamilə yeni bir sıraya işarə edir (diaqrama bax): Lakin bu diaqram tamamilə düzgün deyil; bu yığında əslində nə baş verdiyini nümayiş etdirmir. JDK 6 və JDK 7-də çağırılanda əslində baş verənlər substring()
fərqlidir.
3. JDK 6-da substring()
Sətir tipi massiv növü ilə dəstəklənirchar
. JDK 6-da sinif String
3 sahəni ehtiva edir: char value[]
, int offset
, int count
. Onlar simvolların faktiki massivini, massivdəki birinci simvolun indeksini, sətirdəki simvolların sayını saxlamaq üçün istifadə olunur. Metod çağırıldıqda substring()
, o, yeni sətir yaradır, lakin dəyişənin dəyəri yenə də yığındakı eyni massivi göstərir. İki sətir arasındakı fərq onların simvollarının sayı və massivdəki başlanğıc simvolun indeks dəyəridir. Aşağıdakı kod sadələşdirilmişdir və yalnız problemi nümayiş etdirmək üçün əsasları ehtiva edir.
//JDK 6
String(int offset, int count, char value[]) {
this.value = value;
this.offset = offset;
this.count = count;
}
public String substring(int beginIndex, int endIndex) {
//check boundary
return new String(offset + beginIndex, endIndex - beginIndex, value);
}
4. JDK 6-da substring() ilə yaranan problem
Əgər ÇOX uzun bir siminiz varsa, ancaq hər dəfə istifadə etdiyiniz zaman onun yalnız kiçik bir hissəsinə ehtiyacınız varsasubstring()
. Bu, icra problemlərinə səbəb olacaq, çünki sizə yalnız kiçik bir hissə lazımdır, lakin siz hələ də bütün sətri saxlamalısınız. JDK 6 üçün həll sətri real alt sətirə ötürəcək aşağıdakı koddur:
x = x.substring(x, y) + ""
İstifadəçi STepeR sualı tərtib etdi (şərhinə baxın) və 4-cü bənd əlavə etmək lazım gəldi. "JDK 6-da yaranan problem substring()
" daha geniş nümunədir. Ümid edirəm ki, bu, cavab olacaq və başqalarına problemin nə olduğunu tez bir zamanda anlamağa kömək edəcək. Budur kod:
String a = "aLongLongString";
String b = a.substring(1, 2);
String c = a.substring(2, 6);
Beləliklə, JDK 7-də b
a с
tipli obyektdə String
metodu çağırmaqla yaradılan a substring()
tipli String
obyektlər yığın- L
for b
, ongL
for üçün yeni yaradılmış iki massivə istinad edəcək c
. aLongLongString
Bu iki yeni massiv a-nın istinad etdiyi orijinal massivlə İLƏ Yığında saxlanacaq . Bunlar. orijinal massiv heç yerdə yoxa çıxmır. İndi JDK 6-ya qayıdaq. JDK 6-da yığın tək massivdən ibarətdir aLongLongString
. Kod sətirlərini yerinə yetirdikdən sonra
String b = a.substring(1, 2);
String c = a.substring(2, 6);
obyektlər obyektə uyğun olan yığındakı eyni massivə istinad edir b
: - 1-ci indeksdən 2-ciyə qədər olan elementlərə, - 2-ci indeksdən 6-ya qədər olan elementlərə (nömrələmə 0-dan başlayır, xatırlatma). Bunlar. Aydındır ki, JDK 6-da dəyişənlərə və ya c-yə hər hansı əlavə giriş əslində orijinal massivin istənilən elementlərinin yığına “hesablanması” ilə nəticələnəcək. JDK 7-də dəyişənlərə və ya c-yə hər hansı əlavə giriş artıq yaradılmış və yığında “yaşayan” lazımi kiçik massivlərə girişə səbəb olacaq. Bunlar. Aydındır ki, JDK 7 bu kimi hallarda fiziki olaraq daha çox yaddaş istifadə edir. Ancaq mümkün variantı təsəvvür edək: dəyişənin müəyyən alt sətirləri dəyişənlərə təyin edilir və gələcəkdə hər kəs yalnız onlardan istifadə edir - obyektlər və . Artıq heç kim sadəcə a dəyişəninə daxil olmur, ona heç bir istinad yoxdur (məqalənin müəllifi bunu nəzərdə tutur). Nəticədə, müəyyən bir zamanda, zibil kollektoru işə salınır və (ən ümumi formada, əlbəttə ki) biz 2 fərqli vəziyyət alırıq: JDK 6 : obyekt məhv edilir (zibil yığılır) , AMMA - orijinal nəhəng yığındakı massiv canlıdır; daim istifadə olunur və . JDK 7: a obyekti yığındakı orijinal massivlə birlikdə məhv edilir. Bu, JDK 6-da yaddaş sızmasına səbəb ola biləcək məqamdır. c
a
b
c
b
b
b
c
a
b
c
a
b
c
5. JDK 7-də substring()
Metod JDK 7-də təkmilləşdirilmişdir. JDK 7-dəsubstring()
əslində yığında yeni massiv yaradır.
//JDK 7
public String(char value[], int offset, int count) {
//check boundary
this.value = Arrays.copyOfRange(value, offset, offset + count);
}
public String substring(int beginIndex, int endIndex) {
//check boundary
int subLen = endIndex - beginIndex;
return new String(value, beginIndex, subLen);
}
GO TO FULL VERSION