Түпнұсқа: Java жолын « » немесе конструктор арқылы жасау керек пе? X Wang арқылы Java тілінде жолды екі әдіс арқылы жасауға болады:
String x = "abc";
String y = new String("abc");
Қос тырнақшаларды пайдалану мен конструкторды пайдаланудың айырмашылығы неде?
1. Қос тырнақшаға қарсы Конструктор
Бұл сұраққа екі қарапайым мысалды қарау арқылы жауап беруге болады. 1-мысал:String a = "abcd";
String b = "abcd";
System.out.println(a == b); // True
System.out.println(a.equals(b)); // True
a==b
ақиқат, себебі олардың a
екеуі де b
бір нысанға сілтеме жасайды – әдіс аймағында литерал (төмендегі жолдың литералы) ретінде жарияланған жолға (оқырманды ресурстағы дереккөзге сілтеме жасаймыз: Java тілін түсінуге арналған ең жақсы 8 диаграмма , 8-диаграмма). Бір жолдың литералы бірнеше рет жасалғанда, жадта жолдың тек бір данасы ғана сақталады (біздің жағдайда «abcd»). Бұл «жол интернингі» деп аталады. Компиляция уақытында өңделген барлық жол тұрақтылары Java-да автоматты түрде интернацияланады. 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
жалған, себебі c
олар d
жадтағы (үймедегі) екі түрлі нысанға сілтеме жасайды. Әртүрлі нысандарда әрқашан әртүрлі сілтемелер болады. Бұл диаграмма жоғарыда сипатталған екі жағдайды көрсетеді:
2. Бағдарламаның орындалу сатысындағы интернинг жолдары
Author LukasEder-ге алғысын білдіреді (төмендегі түсініктеме оның): Жолдық интернинг бағдарламаны орындау кезінде де орын алуы мүмкін, тіпті конструкторлар арқылы екі жол жасалған болса да: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. Қос тырнақшаларды қашан және конструкторларды қашан қолдану керек
Литералды «abcd» әрқашан String типті болғандықтан, конструкторды пайдалану қосымша қажетсіз нысанды жасайды. Осылайша, егер сізге жолды жасау қажет болса, қос тырнақшаларды пайдалану керек. Үймеде жаңа нысан жасау қажет болса, конструкторды пайдалану керек. Пайдалану жағдайлары осы жерде көрсетілген (түпнұсқа) . (Төменде аударылған мәтінді ұсынамын. Бірақ мен әлі де осы сілтемедегі комментаторлардың codeымен танысуды ұсынамын.)JDK 6 және JDK 7 ішіндегі substring() әдісі
JDK 6 және JDK 7 ішіндегі substring() әдісі By X Wangsubstring(int beginIndex, int endIndex)
JDK 6 және JDK 7 әдістері әртүрлі. Бұл айырмашылықтарды білу бұл әдісті жақсырақ пайдалануға көмектеседі. Оқуға ыңғайлы болу үшін төменде substring()
біз толық синтаксисті айтамыз, яғни. substring(int beginIndex, int endIndex)
.
1. Substring() не істейді?
Әдісsubstring(int beginIndex, int endIndex)
таңба нөмірінен басталатын beginIndex
және таңба нөмірімен аяқталатын жолды қайтарады endIndex-1
.
String x = "abcdef";
x = x.substring(1,3);
System.out.println(x);
Шығару:
bc
2. Substring() шақырылғанда не болады?
Өзгермейтіндіктенx
x нәтижесін тағайындағанда x.substring(1,3)
, x
ол мүлдем жаңа жолды көрсететінін білуіңіз мүмкін (диаграмманы қараңыз): Дегенмен, бұл диаграмма толығымен дұрыс емес; бұл үймеде не болып жатқанын көрсетпейді. JDK 6 және JDK 7-де шақырылған кезде іс жүзінде не болады substring()
.
3. JDK 6 ішіндегі substring()
Жол түріне массив түрі қолдау көрсетедіchar
. JDK 6-да сыныпта String
3 өріс бар: char value[]
, int offset
, int count
. Олар символдардың нақты массивін, массивтегі бірінші символдың индексін, жолдағы символдар санын сақтау үшін қолданылады. Әдіс шақырылғанда substring()
, ол жаңа жолды жасайды, бірақ айнымалының мәні әлі де үймедегі бірдей массивке нұсқайды. Екі жолдың айырмашылығы олардың таңбалар саны және массивтегі бастапқы таңбаның индекс мәні болып табылады. Төмендегі code жеңілдетілген және тек мәселені көрсету үшін негіздерді қамтиды.
//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 ішіндегі substring() арқылы туындаған мәселе
Егер сізде ӨТЕ ұзын жол болса, бірақ сізге оның аз ғана бөлігі қажет болса, оны пайдаланған сайын аласызsubstring()
. Бұл орындау проблемаларын тудырады, себебі сізге тек кішкене бөлік қажет, бірақ әлі де бүкіл жолды сақтау керек. JDK 6 үшін шешім жолды нақты ішкі жолға шығаратын төмендегі code болып табылады:
x = x.substring(x, y) + ""
STepeR пайдаланушысы сұрақ құрастырды (оның түсініктемесін қараңыз) және 4-тармақты қосу қажет болды. « substring()
JDK 6-да туындаған мәселе» кеңірек мысал болып табылады. Бұл жауап болады және басқаларға мәселенің не екенін тез анықтауға көмектеседі деп үміттенемін. Міне code:
String a = "aLongLongString";
String b = a.substring(1, 2);
String c = a.substring(2, 6);
Сонымен, JDK 7 жүйесінде b
a типті с
нысандағы String
әдісті шақыру арқылы жасалған a substring()
түрінің нысандары String
үймедегі жаңадан жасалған екі массивке сілтеме жасайды - L
for b
, ongL
for c
. Бұл екі жаңа массив а арқылы сілтеме жасалған бастапқы массивпен бірге үймеде сақталады aLongLongString
. Анау. бастапқы массив еш жерде жоғалмайды. Енді JDK 6-ға оралайық. JDK 6-да үйме бір массивтен тұрады aLongLongString
. Код жолдарын орындағаннан кейін
String b = a.substring(1, 2);
String c = a.substring(2, 6);
нысандар нысанға сәйкес үймедегі бірдей массивке сілтеме жасайды b
: - 1-ші индекстен 2-ге дейінгі элементтерге, - 2-ші индекстен 6-ға дейінгі элементтерге (нөмірлеу 0-ден басталады, еске салу). Анау. JDK 6-дағы айнымалыларға немесе c-ға кез келген әрі қарай қол жеткізу шын мәнінде бастапқы массивтің қажетті элементтерін үймеге «есептелуге» әкелетіні анық. JDK 7-де айнымалыларға немесе c-ға кез келген әрі қарай қол жеткізу бұрыннан жасалған және үймеде «тіршілік ететін» қажетті кішірек массивтерге қол жеткізуді тудырады. Анау. JDK 7 осындай жағдайларда физикалық тұрғыдан көбірек жадты пайдаланады. Бірақ ықтимал нұсқаны елестетіп көрейік: айнымалының белгілі бір ішкі жолдары айнымалыларға тағайындалады және болашақта барлығы оларды ғана пайдаланады - нысандар және . Енді ешкім a айнымалысына қол жеткізе алмайды, оған сілтемелер жоқ (мақала авторы осыны білдіреді). Нәтижесінде, белгілі бір уақытта қоқыс жинағыш іске қосылады және (ең жалпы түрде, әрине) біз 2 түрлі жағдайды аламыз: JDK 6 : an object жойылды (қоқыс жиналады) , БІРАҚ - бастапқы үлкен массив. үйіндіде тірі; ол үнемі пайдаланылады және . JDK 7: а нысаны үймедегі бастапқы массивпен бірге жойылады. Бұл JDK 6-дағы жадтың ағып кетуіне әкелетін нүкте. c
a
b
c
b
b
b
c
a
b
c
a
b
c
5. JDK 7 ішіндегі substring()
Әдіс JDK 7-де жетілдірілді. JDK 7-деsubstring()
ол үймеде жаңа массив жасайды.
//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