JavaRush /Blog Java /Random-PL /metoda charAt() w Javie

metoda charAt() w Javie

Opublikowano w grupie Random-PL
Istnieje wiele podstawowych technik, których używamy regularnie, nawet o tym nie myśląc. A co, jeśli się nad tym zastanowić i przyjrzeć się, jak wdrażane są pewne pozornie proste metody? Myślę, że to pomoże nam zbliżyć się o krok do Javy) charAt() w Javie - 1Wyobraźmy sobie sytuację, w której musimy wyodrębnić pewien znak z jakiegoś ciągu znaków. Jak możemy to zrobić w Javie? Na przykład dzwoniąc do Java String charAt. O tej metodzie charAt()porozmawiamy w dzisiejszym artykule.

Składnia

char charAt(int index)zwraca wartość char o określonym indeksie. Indeks waha się od 0 do length()-1. Oznacza to, że pierwsza charwartość ciągu znajduje się w index 0, następna w index 1itd., tak jak ma to miejsce w przypadku indeksowania tablicy.

Przykład

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));
}
Pierwsza linia zajmuje pierwszy znak, druga linia zajmuje drugi i tak dalej. Ponieważ nie println, ale jest tutaj użyte print, bez nowej linii, otrzymamy następujące dane wyjściowe na konsolę:

Java
Jeżeli chardany indeks jest reprezentowany jako Unicode, wynikiem metody java charAt()będzie znak reprezentujący ten Unicode:
System.out.println("J\u0061vaRush".charAt(1));
Wyjście konsoli:

a

Co kryje się „pod maską”

Jak to działa, pytasz? charAt() w Javie - 2Faktem jest, że każdy obiekt Stringzawiera tablicę bytezawierającą bajty elementów danej linii:
private final byte[] value;
A oto sama metoda chatAt:
public char charAt(int index) {
   if (isLatin1()) {
       return StringLatin1.charAt(value, index);
   } else {
       return StringUTF16.charAt(value, index);
   }
}
isLatin1- flaga wskazująca, czy nasz ciąg zawiera tylko znaki łacińskie, czy też nie. To określa, która metoda zostanie wywołana jako następna.

isLatin1 = prawda

Jeśli ciąg zawiera tylko znaki łacińskie, wywoływana jest metoda charAtklasy statycznej StringLatin1:
public static char charAt(byte[] value, int index) {
   if (index < 0 || index >= value.length) {
       throw new StringIndexOutOfBoundsException(index);
   }
   return (char)(value[index] & 0xff);
}
Pierwszym krokiem jest sprawdzenie, czy przychodzący indeks jest większy lub równy 0 i czy nie wykracza poza wewnętrzną tablicę bajtów, a jeśli tak nie jest, zgłaszany jest wyjątek new StringIndexOutOfBoundsException(index). Jeśli kontrole zostaną zaliczone, potrzebny nam element zostanie zabrany. Na koniec widzimy:
  • &rozciąga się dla operacji binarnych na bytebitowe
  • 0xffnic nie robi, a jedynie &wymaga argumentu
  • (char)konwertuje dane z tabeli ASCII dochar

isLatin1 = fałsz

Gdybyśmy mieli więcej niż tylko znaki łacińskie, klasa zostanie użyta StringUTF16i wywołana zostanie jej metoda statyczna:
public static char charAt(byte[] value, int index) {
   checkIndex(index, value);
   return getChar(value, index);
}
Co z kolei wywołuje:
public static void checkIndex(int off, byte[] val) {
   String.checkIndex(off, length(val));
}
I deleguje do metody statycznej String:
static void checkIndex(int index, int length) {
   if (index < 0 || index >= length) {
       throw new StringIndexOutOfBoundsException("index " + index +
                                                 ", length " + length);
   }
}
Tutaj faktycznie sprawdza się, czy indeks jest ważny: ponownie, czy jest dodatni, czy zerowy i czy nie przekroczył granic tablicy. Ale w klasie StringUTF16metody charAtwywołanie drugiej metody będzie bardziej interesujące:
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));
}
Zacznijmy analizować, co się tu właściwie dzieje. Pierwszym krokiem na początku metody jest ponowne sprawdzenie ważności indeksu. Aby zrozumieć, co stanie się dalej, musisz zrozumieć: kiedy znak inny niż łaciński wchodzi do tablicy value, jest on reprezentowany przez dwa bajty (dwie komórki tablicy). Jeśli mamy ciąg dwóch znaków cyrylicy - „av”, to:
  • dla „a” jest to para bajtów - 48 i 4;
  • dla „w” - 50 i 4.
Oznacza to, że jeśli utworzymy ciąg „av”, będzie on miał tablicę value- {48, 4, 50, 4} W rzeczywistości ta metoda działa z dwiema komórkami tablicy value. Dlatego kolejnym krokiem jest przesunięcie index <<= 1;, aby dostać się bezpośrednio do indeksu pierwszego bajtu żądanego znaku w tablicy value. Powiedzmy teraz, że mamy ciąg znaków "абвг". Wtedy tablica wartości będzie wyglądać następująco: {48, 4, 49, 4, 50, 4, 51, 4}. Prosimy o trzeci element ciągu i wtedy reprezentacja binarna to 00000000 00000011. Po przesunięciu o 1 otrzymamy 00000000 00000110, czyli index = 6. Aby odświeżyć swoją wiedzę na temat operacji bitowych, możesz przeczytać ten artykuł . charAt() w Javie - 4Widzimy też pewne zmienne: HI_BYTE_SHIFT w tym przypadku jest to 0, LO_BYTE_SHIFTw tym przypadku jest to 8. W ostatniej linijce tej metody:
  1. Element jest pobierany z tablicy wartości i przesuwany bitowo o HI_BYTE_SHIFT, czyli o 0, podczas zwiększania index +1.

    W przykładzie z ciągiem "абвг"szósty bajt – 51 – pozostanie taki, ale jednocześnie indeks wzrośnie do 7.

  2. Następnie pobierany jest kolejny element tablicy i przesuwany bitowo w ten sam sposób, ale o LO_BYTE_SHIFT, czyli o 8 bitów.

    A gdybyśmy mieli bajt 4, który ma reprezentację binarną - 00000000 00000100, to po przesunięciu o 8 bitów otrzymamy 00000100 00000000. Jeśli jest to liczba całkowita - 1024.

  3. Następnie dla tych dwóch wartości następuje operacja | (OR).

    A gdybyśmy mieli bajty 51 i 1024, które w reprezentacji binarnej wyglądały jak 00000000 00110011 i 00000100 00000000, to po operacji ORotrzymamy 00000100 00110011, co oznacza liczbę 1075 w systemie dziesiętnym.

    Otóż ​​na koniec liczba 1075 jest konwertowana na typ char, a przy konwersji int -> char wykorzystywana jest tablica ASCII, a w niej pod liczbą 1075 znajduje się znak 'g'.

Właściwie w ten sposób otrzymujemy „g” w wyniku metody stosowanej charAt()w programowaniu w Javie.
Komentarze
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION