Heç düşünmədən müntəzəm olaraq istifadə etdiyimiz bir çox əsas texnikalar var. Yaxşı, bu barədə düşünsəniz və bəzi sadə görünən metodların necə həyata keçirildiyinə baxsanız nə olacaq? Düşünürəm ki, bu bizə Java-ya bir addım yaxınlaşmağa kömək edəcək) Gəlin elə bir vəziyyəti təsəvvür edək ki, hansısa sətirdə müəyyən simvol çıxarmaq lazımdır. Bunu Java-da necə edə bilərik? Məsələn, zəng edərək
Java String charAt
. Bugünkü məqalədə üsul haqqında charAt()
danışacağıq .
Sintaksis
char charAt(int index)
müəyyən edilmiş indeksdə char dəyərini qaytarır. İndeks 0 ilə arasında dəyişir length()-1
. Yəni, serialın indeksləşdirilməsində olduğu kimi , char
ardıcıllığın birinci qiyməti -də index 0
, sonrakısı --da və s.-dir.index 1
Misal
public static void main(String[] args) {
System.out.print("JavaRush".charAt(0));
System.out.print("JavaRush".charAt(1));
System.out.print("JavaRush".charAt(2));
System.out.print("JavaRush".charAt(3));
}
Birinci sətir birinci simvolu, ikinci sətir ikincini götürür və s. Olmadığından println
, lakin burada print
yeni sətir olmadan istifadə edildiyi üçün konsola aşağıdakı çıxışı alacağıq:
Java
Əgər char
verilmiş indeks Unicode kimi göstərilibsə, metodun nəticəsi java charAt()
bu Unicode-u təmsil edən simvol olacaq:
System.out.println("J\u0061vaRush".charAt(1));
Konsol çıxışı:
a
"Başlıq altında" nədir
Necə işləyir, soruşursan? Fakt budur ki, hər bir obyekt verilmiş sətrin elementlərinin baytları olanString
bir massiv ehtiva edir :byte
private final byte[] value;
Və burada metodun özü chatAt
:
public char charAt(int index) {
if (isLatin1()) {
return StringLatin1.charAt(value, index);
} else {
return StringUTF16.charAt(value, index);
}
}
isLatin1
- sətirimizdə yalnız Latın hərflərindən ibarət olub-olmadığını göstərən bayraq. Bu, növbəti hansı metodun çağırılacağını müəyyənləşdirir.
isLatın1 = doğrudur
Sətirdə yalnız Latın simvolları varsa, statikcharAt
sinif metodu adlanır StringLatin1
:
public static char charAt(byte[] value, int index) {
if (index < 0 || index >= value.length) {
throw new StringIndexOutOfBoundsException(index);
}
return (char)(value[index] & 0xff);
}
İlk addım, daxil olan indeksin 0-dan böyük və ya bərabər olduğunu və daxili bayt massivindən kənara çıxmadığını yoxlamaqdır və əgər belə deyilsə, istisna atılır new StringIndexOutOfBoundsException(index)
. Əgər yoxlamalar keçibsə, o zaman bizə lazım olan element götürülür. Sonda görürük:
&
ikili əməliyyat üçünbyte
bit istiqamətində uzanır0xff
&
arqument tələb etməkdən başqa heç nə etmir(char)
ASCII cədvəlindən məlumatları dəyişdirirchar
isLatın1 = yalan
Əgər bizdə sadəcə latın hərflərindən çox olsa, sinif istifadə olunacaqStringUTF16
və onun statik metodu çağırılacaq:
public static char charAt(byte[] value, int index) {
checkIndex(index, value);
return getChar(value, index);
}
Bu da öz növbəsində çağırır:
public static void checkIndex(int off, byte[] val) {
String.checkIndex(off, length(val));
}
Və o, statik bir üsula həvalə edir String
:
static void checkIndex(int index, int length) {
if (index < 0 || index >= length) {
throw new StringIndexOutOfBoundsException("index " + index +
", length " + length);
}
}
Burada, əslində, indeksin etibarlı olub-olmadığını yoxlamaq üçün yoxlama aparılır: yenə müsbət və ya sıfır olub-olmaması və massivin hüdudlarından kənara çıxmaması. StringUTF16
Ancaq metoddakı bir sinifdə charAt
ikinci metodu çağırmaq daha maraqlı olacaq:
static char getChar(byte[] val, int index) {
assert index >= 0 && index < length(val) : "Trusted caller missed bounds check";
index <<= 1;
return (char)(((val[index++] & 0xff) << HI_BYTE_SHIFT) |
((val[index] & 0xff) << LO_BYTE_SHIFT));
}
Burada əslində nə baş verdiyini təhlil etməyə başlayaq. Metodun başlanğıcındakı ilk addım indeksin etibarlılığını yoxlamaqdır. Bundan sonra nə baş verdiyini başa düşmək üçün başa düşməlisiniz: latın olmayan simvol massivə daxil olduqda value
, o, iki bayt (iki massiv hüceyrəsi) ilə təmsil olunur. İki kiril hərfindən ibarət bir sətirimiz varsa - "av", onda:
- 'a' üçün bu bir cüt baytdır - 48 və 4;
- "in" üçün - 50 və 4.
value
- {48, 4, 50, 4} Əslində bu üsul iki massiv xanası ilə işləyir value
. Beləliklə, növbəti addım index <<= 1;
massivdə istədiyiniz simvolun ilk baytının indeksinə birbaşa keçməkdir value
. İndi deyək ki, bir simimiz var "абвг"
. Sonra dəyər massivi belə görünəcək: {48, 4, 49, 4, 50, 4, 51, 4}. Biz sətirin üçüncü elementini soruşuruq və sonra ikili təsvir 00000000 00000011-dir. 1-ə sürüşdürdükdə biz 00000000 00000110 alırıq, yəni index = 6
. Bitvi əməliyyatlar haqqında biliklərinizi yeniləmək üçün bu məqaləni oxuya bilərsiniz . Bəzi dəyişənləri də görürük: HI_BYTE_SHIFT
bu halda 0. LO_BYTE_SHIFT
bu halda 8. Bu metodun sonuncu sətirində:
- Element dəyər massivindən götürülür və
HI_BYTE_SHIFT
artırılarkən bit istiqamətində , yəni 0-a sürüşdürülürindex +1
.Simli misalda
"абвг"
altıncı bayt - 51 - belə qalacaq, lakin eyni zamanda indeks 7-ə qədər artır. - Bundan sonra massivin növbəti elementi alınır və eyni şəkildə, lakin LO_BYTE_SHIFT, yəni 8 bit ilə bit istiqamətində sürüşdürülür.
Əgər ikili təsviri olan 4 baytımız varsa - 00000000 00000100, onda 8 bitə keçdikdən sonra 00000100 00000000 olacaq. Əgər tam ədəddirsə - 1024.
- Sonra, bu iki dəyər üçün əməliyyata əməl edin
| (OR)
.Əgər ikili təsvirdə 00000000 00110011 və 00000100 00000000 kimi görünən 51 və 1024 baytlarımız olsaydı, əməliyyatdan sonra
OR
biz 00000100 00110011 alacağıq, bu da onluq sistemdə 1075 deməkdir.Yaxşı, sonda 1075 rəqəmi char tipinə çevrilir və int -> char çevirərkən ASCII cədvəlindən istifadə olunur və orada 1075 rəqəminin altında 'g' simvolu var.
charAt()
Əslində, Java proqramlaşdırmasında metodun nəticəsi olaraq 'g' alırıq .
GO TO FULL VERSION