Ohjelmointi

Merkkijonovertailut Java-kielellä

Java-sovelluksessa Merkkijono luokka kapseloi joukon hiiltyä. Yksinkertaistetusti, Merkkijono on joukko merkkejä, joita käytetään sanojen, lauseiden tai minkä tahansa muun haluamasi tiedon kirjoittamiseen.

Kapselointi on yksi olio-ohjelmoinnin tehokkaimmista käsitteistä. Kapseloinnin takia sinun ei tarvitse tietää Miten merkkijono-luokka toimii; sinun tarvitsee vain tietää mitä sen käyttöliittymässä käytettäviä menetelmiä.

Kun katsot Merkkijono luokan Java, näet kuinka taulukko hiiltyä on koteloitu:

 public String (char arvo []) {tämä (arvo, 0, arvo.pituus, nolla); } 

Harkitse fyysinen esine: auto, jotta ymmärrät kapselointia paremmin. Täytyykö sinun tietää, miten auto toimii konepellin alla ajaaksesi sitä? Ei tietenkään, mutta sinun on tiedettävä, mitä auton rajapinnat tekevät: esimerkiksi kaasupoljin, jarrut ja ohjauspyörä. Jokainen näistä rajapinnoista tukee tiettyjä toimintoja: kiihdytä, jarruta, käänny vasemmalle, käänny oikealle. Sama on olio-ohjelmoinnissa.

Ensimmäinen blogini Java-haastajat -sarja esitteli menetelmän ylikuormituksen, joka on tekniikka Merkkijono luokka käyttää laajasti. Ylikuormitus voi tehdä luokastasi todella joustavan, mukaan lukien Merkkijono:

 public String (String original) {} public String (char value [], int offset, int count) {} public String (int [] codePoints, int offset, int count) {} public String (tavua tavuja [], int offset , int pituus, String charsetName) {} // Ja niin edelleen ... ... 

Sen sijaan, että yrität ymmärtää, miten Merkkijono luokassa toimii, tämä Java Challenger auttaa sinua ymmärtämään mitä se tekee ja Miten käyttää sitä koodissasi.

Mikä on String-allas?

Merkkijono on mahdollisesti eniten käytetty Java-luokka. Jos muistikohteeseen luotiin uusi objekti aina, kun käytimme a Merkkijono, tuhlaisimme paljon muistia. Merkkijono pool ratkaisee tämän ongelman tallentamalla kullekin vain yhden objektin Merkkijono arvo, kuten alla on esitetty.

Rafael Chinelato Del Nero

Vaikka loimme a Merkkijono muuttuja Duke ja JuggyMerkkijonos, vain kaksi objektia luodaan ja tallennetaan muistin kasaan. Katso todiste seuraavasta koodinäytteestä. (Muistakaa, että==”Java-operaattoria käytetään vertaamaan kahta objektia ja selvittämään, ovatko ne samat.)

 Merkkijono = "Juggy"; String anotherJuggy = "Juggy"; System.out.println (juggy == anotherJuggy); 

Tämä koodi palautuu totta koska nämä kaksi Merkkijonos osoittavat samaan objektiin Merkkijono uima-allas. Niiden arvot ovat samat.

Poikkeus: Uusi operaattori

Katsokaa nyt tätä koodia - se näyttää samanlaiselta kuin edellinen näyte, mutta siinä on ero.

 Merkkijono herttua = uusi kieli ("herttua"); String anotherDuke = uusi merkkijono ("herttua"); System.out.println (herttua == anotherDuke); 

Edellisen esimerkin perusteella saatat ajatella, että tämä koodi palaa totta, mutta se on itse asiassa väärä. Lisäämällä Uusi operaattori pakottaa luomaan uuden Merkkijono muistin kasaan. Siten JVM luo kaksi erilaista objektia.

Alkuperäiset menetelmät

A natiivi menetelmä Java on menetelmä, joka käännetään C-kielellä, yleensä muistin manipuloimiseksi ja suorituskyvyn optimoimiseksi.

Jousisarjat ja harjoittelumenetelmä

Voit tallentaa a Merkkijono että Merkkijono uima-altaassa, käytämme tekniikkaa nimeltä Merkkijono harjoittelu. Tässä on mitä Javadoc kertoo meille työharjoittelija() menetelmä:

 / ** * Palauttaa merkkijono-objektille kanonisen esityksen. * * Alun perin tyhjiä merkkijonoja ylläpitää yksityisesti * luokka {@code String}. * * Kun intern-menetelmää käytetään, jos pooli sisältää jo * merkkijonon, joka on yhtä suuri kuin tämä {@code String} -objekti, määritetty * {@link #equals (Object)} -menetelmän avulla, altaan merkkijono on * palasi. Muussa tapauksessa tämä {@code String} -objekti lisätään * pooliin ja viittaus tähän {@code String} -objektiin palautetaan. * * Tästä seuraa, että minkä tahansa kahden merkkijonon {@code s} ja {@code t} kohdalla * {@code s.intern () == t.intern ()} on {@code true} * jos ja vain jos { @code s.equals (t)} on {@code true}. * * Kaikki kirjaimelliset merkkijonot ja merkkijonoarvoiset vakiolausekkeet * internoidaan. Merkkijonolitraalit on määritelty * Java ™ -kielimäärityksen osassa 3.10.5. * * @ palauttaa merkkijonon, jonka sisältö on sama kuin tällä merkkijonolla, mutta on * taatusti peräisin ainutlaatuisten merkkijonojen joukosta. * @jls 3.10.5 Jousisoiton literaalit * / julkinen syntyperäinen kielisoittaja (); 

työharjoittelija() menetelmää käytetään varastointiin Merkkijonos a: ssa Merkkijono uima-allas. Ensinnäkin se tarkistaa, onko Merkkijono luomasi jo olemassa poolissa. Jos ei, se luo uuden Merkkijono altaassa. Kulissien takana, logiikka Merkkijono poolointi perustuu Flyweight-kuvioon.

Huomaa nyt, mitä tapahtuu, kun käytämme Uusi avainsana pakottaa luomaan kaksi Merkkijonos:

 Merkkijono herttua = uusi kieli ("herttua"); Merkkijono herttua2 = uusi merkkijono ("herttua"); System.out.println (herttua == herttua2); // Tulos on väärä tässä System.out.println (duke.intern () == duke2.intern ()); // Tulos on totta tässä 

Toisin kuin edellisessä esimerkissä Uusi avainsana, tässä tapauksessa vertailu osoittautuu totta. Tämä johtuu siitä, että työharjoittelija() menetelmä varmistaa Merkkijonos tallennetaan uima-altaaseen.

Yhtä menetelmä String-luokan kanssa

on yhtä suuri () -menetelmää käytetään varmistamaan, onko kahden Java-luokan tila sama. Koska on yhtä suuri () on peräisin Esine luokka, jokainen Java-luokka perii sen. Mutta on yhtä suuri () Menetelmä on ohitettava, jotta se toimisi oikein. Tietysti, Merkkijono ohittaa on yhtä suuri ().

Katso:

 julkinen looginen arvo on yhtä suuri (Object anObject) {if (this == anObject) {return true; } if (stringin anObject-ilmentymä) {String aString = (String) anObject; if (kooderi () == aString.coder ()) {return onLatin1 ()? StringLatin1.equals (arvo, aString.value): StringUTF16.equals (arvo, aString.value); }} return false; } 

Kuten näette, Merkkijono luokan arvon on oltava on yhtä suuri () eikä objektiviittausta. Ei ole väliä, onko objektiviite erilainen; valtion tila Merkkijono verrataan.

Yleisimmät merkkijonomenetelmät

On vain yksi viimeinen asia, joka sinun on tiedettävä ennen Merkkijono vertailuhaaste. Harkitse näitä yleisiä menetelmiä Merkkijono luokka:

 // Poistaa välilyönnit reunaviivasta () // Hakee alimerkin indeksoimalla alimerkkijonon (int beginIndex, int endIndex) // Palauttaa merkkijonon merkkien pituuden () // Korvaa merkkijonon, regexiä voidaan käyttää. aizstaaKaikki (merkkijonon regex, merkkijonon vaihto) // Tarkista, onko merkkijonossa määritetty CharSequence sisältää (CharSequences) 

Ota String-vertailuhaaste!

Kokeillaan, mitä olet oppinut Merkkijono luokan nopea haaste.

Vertaile tähän haasteeseen useita Merkkijonos käyttämällä tutkittuja käsitteitä. Katsoessasi alla olevaa koodia voitko määrittää kunkin lopullisen arvon tuloksia muuttuja?

 public class ComparisonStringChallenge {public static void main (String ... doYourBest) {String result = ""; tulos + = "voimakas koodi" .trim () == "tehokas koodi"? "0": "1"; tulos + = "FlexibleCode" == "FlexibleCode"? "2": "3"; tulos + = uusi merkkijono ("doYourBest") == uusi merkkijono ("doYourBest")? "4": "5"; tulos + = uusi merkkijono ("noBugsProject"). on yhtä suuri ("noBugsProject")? "6": "7"; tulos + = uusi merkkijono ("breakYourLimits"). harjoittelija () == uusi merkkijono ("breakYourLimits"). harjoittelija ()? "8": "9"; System.out.println (tulos); }} 

Mikä tulos edustaa tulosmuuttujan lopullista arvoa?

A: 02468

B: 12469

C: 12579

D.: 12568

Tarkista vastauksesi täältä.

Mitä juuri tapahtui? Merkkijonon käyttäytymisen ymmärtäminen

Koodin ensimmäisellä rivillä näemme:

 tulos + = "voimakas koodi" .trim () == "tehokas koodi"? "0": "1"; 

vaikkakin Merkkijono on sama jälkeen trimmata() menetelmää käytetään, Merkkijono"Tehokas koodi" oli erilainen alussa. Tässä tapauksessa vertailu on väärä, koska kun trimmata() menetelmä poistaa välilyöntejä rajoilta se pakottaa luomaan uuden Merkkijono uuden operaattorin kanssa.

Seuraavaksi näemme:

 tulos + = "FlexibleCode" == "FlexibleCode"? "2": "3"; 

Ei mitään mysteeriä täällä Merkkijonos ovat samat Merkkijono uima-allas. Tämä vertailu palaa totta.

Seuraavaksi meillä on:

 tulos + = uusi merkkijono ("doYourBest") == uusi merkkijono ("doYourBest")? "4": "5"; 

Käyttämällä Uusi varattu avainsana pakottaa luomaan kaksi uutta Merkkijonos riippumatta siitä, ovatko he samanarvoisia vai ei. Tässä tapauksessa vertailu on väärä vaikka Merkkijono arvot ovat samat.

Seuraava on:

 tulos + = uusi merkkijono ("noBugsProject"). on yhtä suuri ("noBugsProject")? "6": "7"; 

Koska olemme käyttäneet on yhtä suuri () menetelmä, arvo Merkkijono verrataan eikä objektin esiintymää. Siinä tapauksessa ei ole väliä, ovatko objektit erilaisia, koska arvoa verrataan. Tämä vertailu palaa totta.

Lopuksi meillä on:

 tulos + = uusi merkkijono ("breakYourLimits"). harjoittelija () == uusi merkkijono ("breakYourLimits"). harjoittelija ()? "8": "9"; 

Kuten olet aiemmin nähnyt, työharjoittelija() menetelmä asettaa Merkkijono että Merkkijono uima-allas. Molemmat Merkkijonos osoittavat samaan kohteeseen, joten tässä tapauksessa vertailu on totta.

Video-haaste! Merkkijonojen virheenkorjaus

Virheenkorjaus on yksi helpoimmista tavoista hyödyntää ohjelmointikonsepteja täysin ja parantaa samalla koodiasi. Tässä videossa voit seurata mukana, kun minä virheenkorjaan ja selitän Java Strings -haasteen:

Merkkijonojen yleiset virheet

Voi olla vaikea tietää, ovatko kaksi Merkkijonos osoittavat samaan kohteeseen, varsinkin kun Merkkijonos sisältävät saman arvon. Se auttaa muistamaan, että varatun avainsanan käyttö Uusi johtaa aina uuden objektin luomiseen muistiin, vaikka arvot olisivat samat.

Käyttämällä Merkkijono menetelmiä vertailla Esine viitteet voivat myös olla hankalia. Tärkeintä on, jos menetelmä muuttaa jotain Merkkijono, objektiviitteet ovat erilaiset.

Muutama esimerkki selventämiseksi:

 System.out.println ("herttua" .trim () == "herttua" .trim ()) ;; 

Tämä vertailu on totta, koska trimmata() menetelmä ei luo uutta Merkkijono.

 System.out.println ("herttua" .trim () == "herttua" .trim ()); 

Tässä tapauksessa ensimmäinen trimmata() menetelmä luo uuden Merkkijono koska menetelmä suorittaa toimintansa, joten viitteet ovat erilaiset.

Lopuksi, milloin trimmata() toteuttaa toimintansa, se luo uuden Merkkijono:

 // Trimmimenetelmän toteutus String-luokassa uusi String (Arrays.copyOfRange (val, index, index + len), LATIN1); 

Mitä muista jousista

  • Merkkijonos ovat muuttumattomia, joten a MerkkijonoTilaa ei voi muuttaa.
  • Muistin säästämiseksi JVM pitää Merkkijonos a: ssa Merkkijono uima-allas. Kun uusi Merkkijono luodaan, JVM tarkistaa sen arvon ja osoittaa sen olemassa olevaan objektiin. Jos ei ole Merkkijono kun tämä arvo on poolissa, JVM luo uuden Merkkijono.
  • Käyttämällä == operaattori vertaa objektiviittausta. Käyttämällä on yhtä suuri () - menetelmä vertaa Merkkijono. Samaa sääntöä sovelletaan kaikkiin objekteihin.
  • Kun käytät Uusi operaattori, uusi Merkkijono luodaan Merkkijono uima-allas, vaikka siellä olisi Merkkijono samalla arvolla.

 

Vastausavain

Vastaus tähän Java-haastajaan on vaihtoehto D. Tulos olisi 12568.

Tämän tarinan "String Comparons in Java" julkaisi alun perin JavaWorld.

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