Dotazy a odpovede na rozhovor s Java String

1. Úvod

The String class je jednou z najbežnejšie používaných tried v Jave, ktorá podnietila návrhárov jazykov k špeciálnemu zaobchádzaniu. Toto špeciálne správanie z neho robí jednu z najhorúcejších tém v rozhovoroch Java.

V tomto tutoriáli si prejdeme niektoré z najbežnejších otázok týkajúcich sa pohovorov String.

2. String Základy

Táto časť obsahuje otázky, ktoré sa týkajú String vnútorná štruktúra a pamäť.

Q1. Čo je to reťazec v Jave?

V prostredí Java, a String je interne reprezentovaný poľom bajt hodnoty (alebo char hodnoty pred JDK 9).

Vo verziách do verzie Java 8 vrátane a String bol zložený z nemenného poľa znakov Unicode. Väčšina znakov však vyžaduje iba 8 bitov (1 bajt) aby ich zastupovali namiesto 16 bitov (char veľkosť).

Na zlepšenie spotreby a výkonu pamäte predstavila Java 9 kompaktné reťazce. To znamená, že ak a String obsahuje iba 1-bajtové znaky, bude reprezentovaný pomocou Latinka-1 kódovanie. Ak String obsahuje najmenej 1 viacbajtový znak, bude reprezentovaný ako 2 bajty na znak pomocou kódovania UTF-16.

V jazykoch C a C ++ String je tiež pole znakov, ale v Jave je to samostatný objekt s vlastným API.

Q2. Ako môžeme vytvoriť reťazcový objekt v Jave?

java.lang.String definuje 13 rôznych spôsobov, ako vytvoriť a String. Spravidla však existujú dva:

  • Prostredníctvom a String doslovný:
    Reťazec s = "abc";
  • Cez Nový kľúčové slovo:
    Reťazec s = nový Reťazec ("abc");

Všetky reťazcové literály v Jave sú inštanciami String trieda.

Q3. Je String primitívny alebo odvodený typ?

Reťazec je odvodený typ, pretože má stav a správanie. Napríklad má metódy ako podreťazec (), indexOf ()a rovná sa (), ktoré primitívi nemôžu mať.

Ale keďže ho všetci používame tak často, má niektoré špeciálne vlastnosti, vďaka ktorým sa cíti ako primitív:

  • Aj keď reťazce nie sú uložené v zásobníku hovorov ako primitívy, sú uložené v špeciálnej oblasti pamäte, ktorá sa nazýva oblasť reťazcov
  • Rovnako ako primitíva, aj my môžeme použiť + operátor na strunách
  • A opäť, ako primitíva, môžeme vytvoriť inštanciu a String bez Nový kľúčové slovo

Q4. Aké sú výhody toho, že struny sú nemenné?

Podľa rozhovoru Jamesa Goslinga sú reťazce nemenné na zlepšenie výkonu a bezpečnosti.

V skutočnosti vidíme niekoľko výhod nemenných reťazcov:

  • Fond reťazcov je možný iba vtedy, ak sa reťazce, ktoré už raz boli vytvorené, nikdy nezmenia, pretože sa majú opakovane používať
  • Kód môže bezpečne odovzdať reťazec inej metódes vedomím, že to nemožno touto metódou zmeniť
  • Nezmeniteľné automaticky robí túto triedu bezpečnou pre vlákna
  • Pretože je táto trieda bezpečná pre vlákna, nie je potrebné synchronizovať bežné údaje, čo zase zlepšuje výkon
  • Pretože sa zaručene nezmenia, ich hashcode sa dá ľahko uložiť do medzipamäte

Q5. Ako je reťazec uložený v pamäti?

Podľa špecifikácie JVM, String literály sú uložené v runtime konštantnej oblasti, ktorá je alokovaná z oblasti metódy JVM.

Aj keď je oblasť metódy logicky súčasťou haldy pamäte, špecifikácia nediktuje umiestnenie, veľkosť pamäte ani zásady odvozu odpadu. Môže to byť špecifické pre konkrétnu implementáciu.

Tento súbor runtime konštánt pre triedu alebo rozhranie je zostavený, keď je trieda alebo rozhranie vytvorené JVM.

Q6. Sú internované reťazce vhodné na zber odpadu v Jave?

Áno, všetky Strings vo fonde reťazcov sú spôsobilé na zhromažďovanie odpadkov, ak neexistujú žiadne odkazy z programu.

Q7. Čo je to String Constant Pool?

Pool strún, tiež známy ako String stály bazén alebo String intern pool, je oblasť špeciálnej pamäte, do ktorej ukladá JVM String inštancie.

Optimalizuje výkon aplikácie znížením toho, ako často a koľko reťazcov je alokovaných:

  • Spoločný podnik JVM ukladá iba jednu kópiu konkrétneho záznamu String v bazéne
  • Pri vytváraní nového String, JVM hľadá v skupine a String majúcu rovnakú hodnotu
  • Ak sa zistí, vráti JVM k tomu odkaz String bez pridelenia akejkoľvek ďalšej pamäte
  • Ak sa nenájde, JVM ho pridá do fondu (internuje ho) a vráti jeho referenciu

Q8. Je reťazec bezpečný pre vlákno? Ako?

Reťazce sú skutočne úplne bezpečné pre vlákna, pretože sú nemenné. Akákoľvek trieda, ktorá je nemenná, sa automaticky kvalifikuje na bezpečnosť vlákien, pretože jej nemennosť zaručuje, že sa jej inštancie nezmenia vo viacerých vláknach.

Napríklad, ak vlákno zmení hodnotu reťazca, nová String namiesto úpravy existujúceho sa vytvorí.

Q9. Pre ktoré reťazcové operácie je dôležité dodať miestne nastavenie?

The Miestne nastavenie triedy nám umožňuje rozlišovať medzi kultúrnymi miestami a tiež vhodne formátovať náš obsah.

Pokiaľ ide o String triedy, potrebujeme to pri vykresľovaní reťazcov formát alebo keď sú struny spodného alebo horného puzdra.

V skutočnosti, ak to zabudneme urobiť, môžeme naraziť na problémy s prenosnosťou, bezpečnosťou a použiteľnosťou.

Q10. Čo je kódovanie základných znakov pre struny?

Podľa Reťazecs Javadocs pre verzie do a vrátane Java 8, reťazce sú interne uložené vo formáte UTF-16.

The char údajový typ a java.lang.Postava objekty tiež vychádzajú z pôvodnej špecifikácie Unicode, ktorá definovala znaky ako 16-bitové entity s pevnou šírkou.

Počnúc JDK 9, Struny ktoré obsahujú iba 1-bajtové znaky Latinka-1 kódovanie, zatiaľ čo Struny s najmenej 1 viacbajtovým znakom použite kódovanie UTF-16.

3. The String API

V tejto časti si prediskutujeme niekoľko otázok týkajúcich sa String API.

Q11. Ako môžeme porovnať dva reťazce v Jave? Aký je rozdiel medzi str1 == str2 a str1.Equals (str2)?

Reťazce môžeme porovnávať dvoma rôznymi spôsobmi: použitím rovnosti s operátorom (==) a pomocou znaku rovná sa () metóda.

Oba sa navzájom dosť líšia:

  • Prevádzkovateľ (str1 == str2) kontroluje referenčnú rovnosť
  • Metóda (str1.equals (str2)) kontroly lexikálnej rovnosti

Je pravda, že ak sú dva reťazce lexikálne rovnaké, potom str1.intern () == str2.intern () je tiež pravda.

Spravidla pre porovnanie dvoch Struny pre ich obsah by sme mali vždy použiť String.equals.

Q12. Ako môžeme rozdeliť reťazec v Jave?

The String trieda sama o sebe nám poskytuje Reťazec #rozdeliť metóda, ktorá prijíma oddeľovač regulárneho výrazu. Vracia nám to a Reťazec [] pole:

Reťazec [] parts = "john, peter, mary" .split (","); assertEquals (nový reťazec [] {"john", "peter", "mary"}, časti);

Jedna ošemetná vec rozdeliť je to pri rozdelení prázdneho reťazca, môžeme dostať neprázdne pole:

assertEquals (nový reťazec [] {""}, "" .split (","));

Samozrejme, rozdeliť je len jedným z mnohých spôsobov rozdelenia Javy String.

Q13. Čo je Stringjoiner?

StringJoiner je trieda zavedená v prostredí Java 8 na spájanie samostatných reťazcov do jednej, napríklad vezme zoznam farieb a vráti ich ako reťazec oddelený čiarkami. Môžeme dodať oddeľovač, ako aj predponu a príponu:

StringJoiner joiner = nový StringJoiner (",", "[", "]"); joiner.add ("červená") .add ("zelená") .add ("modrá"); assertEquals ("[červená, zelená, modrá]", joiner.toString ());

Q14. Rozdiel medzi String, Stringbuffer a Stringbuilder?

Struny sú nemenné. To znamená, že ak sa pokúsime zmeniť alebo zmeniť jeho hodnoty, potom Java vytvorí úplne nový String.

Napríklad ak pridáme do reťazca str1 po vytvorení:

Reťazec str1 = "abc"; str1 = str1 + "def";

Potom JVM namiesto úpravy str1, vytvára úplne nový String.

Pre väčšinu jednoduchých prípadov však kompilátor používa interne StringBuilder a optimalizuje vyššie uvedený kód.

Pre zložitejšie kódy, ako sú slučky, vytvorí úplne nový String, zhoršujúci sa výkon. Toto je kde StringBuilder a StringBuffer sú užitočné.

Oboje StringBuilder a StringBuffer v Jave vytvárať objekty, ktoré obsahujú premenlivú postupnosť znakov.StringBuffer je synchronizovaný a teda bezpečný pre vlákna, zatiaľ čo StringBuilder nie je.

Od extra synchronizácie v StringBuffer je zvyčajne zbytočné, výber výkonu môžeme často dosiahnuť zvýšením výkonu StringBuilder.

Q15. Prečo je bezpečnejšie ukladať heslá v char [] poli skôr ako reťazci?

Pretože reťazce sú nemenné, neumožňujú úpravy. Toto správanie nám bráni v prepísaní, úprave alebo vynulovaní jeho obsahu Struny nevhodné na ukladanie citlivých informácií.

Musíme sa spoľahnúť na to, že smetiar odstráni obsah reťazca. Okrem toho vo verzii Java 6 a nižšej boli reťazce uložené v PermGen, čo znamená, že kedysi String bol vytvorený, nikdy to nebolo vyzbierané odpadky.

Použitím a char [] pole, máme nad týmito informáciami úplnú kontrolu.Môžeme ho upraviť alebo úplne utrieť bez toho, aby sme sa spoliehali na smetiara.

Použitím char [] cez String nezabezpečuje úplne informácie; je to len opatrenie navyše, ktoré znižuje možnosť používateľa so zlým úmyslom získať prístup k citlivým informáciám.

Q16. Čo robí metóda String’s intern ()?

Metóda stážista () vytvorí presnú kópiu a String objekt v halde a uloží ho do String konštantná skupina, ktorú JVM udržiava.

Java automaticky internuje všetky reťazce vytvorené pomocou reťazcových literálov, ale ak vytvoríme a String pomocou nového operátora napríklad Reťazec str = nový Reťazec („abc“), potom ho Java pridá na hromadu, rovnako ako každý iný objekt.

Môžeme zavolať stážista () metóda, ktorá povie JVM, aby ho pridal do fondu reťazcov, ak tam ešte neexistuje, a vráti odkaz na tento interný reťazec:

Reťazec s1 = "Baeldung"; Reťazec s2 = nový Reťazec („Baeldung“); Reťazec s3 = nový Reťazec ("Baeldung"). Intern (); assertThat (s1 == s2) .isFalse (); assertThat (s1 == s3) .isTrue ();

Q17. Ako môžeme previesť reťazec na celé číslo a celé číslo na reťazec v Jave?

Najpriamočiarejší prístup k premene a String do an Celé číslo je pomocou Celé čísloparseInt:

int num = Integer.parseInt ("22");

Aby sme to urobili opačne, môžeme použiť Celé číslonatiahnuť:

Reťazec s = Integer.toString (num);

Q18. Čo je String.format () a ako ho môžeme použiť?

Formát reťazca # vráti formátovaný reťazec pomocou zadaného formátovacieho reťazca a argumentov.

Názov reťazca = "Baeldung"; String formatted = String.format ("Názov je% s", názov); assertEquals („Formátovaný titul je Baeldung“);

Musíme tiež pamätať na uvedenie používateľa Miestne nastavenie, pokiaľ nie sme v poriadku s jednoduchým prijatím predvoleného nastavenia operačného systému:

Locale usersLocale = Locale.ITALY; assertEquals ("1.024", String.format (usersLocale, "na výber sú košele%, d. veľa šťastia.", 1024))

Q19. Ako môžeme previesť reťazec na veľké a malé písmená?

String implicitne poskytuje Reťazec # toUpperCase ak chcete zmeniť veľkosť písmen na veľké.

Javadocs nám však pripomína, že musíme špecifikovať používateľské Ľocale na zabezpečenie správnosti:

String s = "Vitajte v Baeldungu!"; assertEquals ("VITAJTE V BAELDUNGU!", s.toUpperCase (Locale.US));

Podobne, na prevedenie na malé písmená, máme Reťazec # toLowerCase:

String s = "Vitajte v Baeldungu!"; assertEquals („vitajte na baeldung!“, s.toLowerCase (Locale.UK));

Q20. Ako môžeme získať pole znakov z reťazca?

String poskytuje toCharArray, ktorá vráti kópiu svojej internej char pole pre-JDK9 (a prevádza String do nového char pole v JDK9 +):

char [] hello = "ahoj" .toCharArray (); assertArrayEquals (nový reťazec [] {'h', 'e', ​​'l', 'l', 'o'}, ahoj);

Q21. Ako by sme previedli reťazec Java na bajtové pole?

Predvolene metóda Reťazec # getBytes () kóduje reťazec do bajtového poľa pomocou predvolenej znakovej sady platformy.

Aj keď API nevyžaduje, aby sme špecifikovali znakovú sadu, mali by sme kvôli zaisteniu bezpečnosti a prenosnosti:

byte [] byteArray2 = "efgh" .getBytes (StandardCharsets.US_ASCII); byte [] byteArray3 = "ijkl" .getBytes ("UTF-8");

4. String- Algoritmy založené na algoritmoch

V tejto časti si prediskutujeme niektoré otázky týkajúce sa programovania Strings.

Q22. Ako môžeme skontrolovať, či sú dva reťazce anagramy v Jave?

Anagram je slovo vytvorené preusporiadaním písmen iného zadaného slova, napríklad „auto“ a „oblúk“.

Na začiatok najskôr skontrolujeme, či sú obidve Struny sú rovnako dlhé alebo nie.

Potom ich prevedieme na char [] pole, zoraďte ich a potom skontrolujte rovnosť.

Q23. Ako môžeme spočítať počet výskytov danej postavy v reťazci?

Java 8 skutočne zjednodušuje agregačné úlohy, ako sú tieto:

long count = "ahoj" .chars (). filter (ch -> (char) ch == 'l'). count (); assertEquals (2, count);

Existuje niekoľko ďalších skvelých spôsobov, ako spočítať písmeno l, vrátane slučiek, rekurzie, regulárnych výrazov a externých knižníc.

Q24. Ako môžeme obrátiť reťazec v Jave?

Existuje mnoho spôsobov, ako to urobiť, najjednoduchším prístupom je použitie obrátiť metóda z StringBuilder (alebo StringBuffer):

Reťazec obrátený = nový StringBuilder ("baeldung"). Reverse (). ToString (); assertEquals ("gnudleab", obrátené);

Q25. Ako môžeme skontrolovať, či je reťazec palindróm alebo nie?

Palindróm je ľubovoľná postupnosť znakov, ktorá sa číta rovnako dozadu aj dopredu, napríklad „madam“, „radar“ alebo „úroveň“.

Ak chcete skontrolovať, či je reťazec palindróm, môžeme začať iterovať daný reťazec dopredu a dozadu v jednej slučke, po jednom znaku. Slučka vystupuje pri prvom nesúlade.

5. Záver

V tomto článku sme prešli niektorými z najrozšírenejších String otázky na pohovor.

Všetky tu použité ukážky kódu sú k dispozícii na GitHub.


$config[zx-auto] not found$config[zx-overlay] not found