Programmering

Streng sammenligninger i Java

I Java er Snor klasse indkapsler en matrix af char. Enkelt sagt, Snor er en række tegn, der bruges til at komponere ord, sætninger eller andre data, du ønsker.

Indkapsling er et af de mest kraftfulde begreber inden for objektorienteret programmering. På grund af indkapsling behøver du ikke vide det hvordan String-klassen fungerer; du skal bare vide det hvad metoder til brug på dens grænseflade.

Når du ser på Snor klasse i Java, kan du se, hvordan matrixen af char er indkapslet:

 public String (char værdi []) {this (værdi, 0, værdi.længde, null); } 

For at forstå indkapsling bedre, overvej et fysisk objekt: en bil. Har du brug for at vide, hvordan bilen fungerer under motorhjelmen for at køre den? Naturligvis ikke, men du behøver at vide, hvad bilens grænseflader gør: ting som gaspedal, bremser og rat. Hver af disse grænseflader understøtter visse handlinger: accelerere, bremse, drej til venstre, drej til højre. Det er det samme i objektorienteret programmering.

Min første blog i Java udfordrere serien introducerede metode overbelastning, som er en teknik Snor klasse bruger i vid udstrækning. Overbelastning kan gøre dine klasser virkelig fleksible, herunder Snor:

 public String (String original) {} public String (char value [], int offset, int count) {} public String (int [] codePoints, int offset, int count) {} public String (byte bytes [], int offset , int længde, String charsetName) {} // Og så videre ... ... 

I stedet for at prøve at forstå, hvordan Snor klasse fungerer, vil denne Java Challenger hjælpe dig med at forstå hvad det gør og hvordan at bruge det i din kode.

Hvad er en streng pool?

Snor er muligvis den mest anvendte klasse i Java. Hvis der blev oprettet et nyt objekt i hukommelsesbunken hver gang, brugte vi en Snor, ville vi spilde en masse hukommelse. Det Snor pool løser dette problem ved kun at gemme et objekt til hver Snor værdi, som vist nedenfor.

Rafael Chinelato Del Nero

Selvom vi skabte en Snor variabel til Hertug og JuggySnors, kun to objekter oprettes og gemmes i hukommelsesbunken. For bevis kan du se på følgende kodeeksempel. (Husk at “==”Operator i Java bruges til at sammenligne to objekter og afgøre, om de er ens.)

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

Denne kode vender tilbage rigtigt fordi de to Snors peger på det samme objekt i Snor pool. Deres værdier er de samme.

En undtagelse: Den 'nye' operatør

Se nu på denne kode - den ligner den forrige prøve, men der er forskel.

 String hertug = ny streng ("hertug"); String anotherDuke = ny streng ("hertug"); System.out.println (hertug == anotherDuke); 

Baseret på det foregående eksempel tror du måske, at denne kode ville vende tilbage rigtigt, men det er faktisk falsk. Tilføjelse af ny operatør tvinger oprettelsen af ​​et nyt Snor i hukommelsesbunken. Således opretter JVM to forskellige objekter.

Indfødte metoder

EN indfødte metode i Java er en metode, der vil blive sammensat ved hjælp af C-sproget, normalt med det formål at manipulere hukommelse og optimere ydeevnen.

Strengpools og metoden intern ()

At gemme en Snor i Snor pool, bruger vi en teknik kaldet Snor praktikant. Her er hvad Javadoc fortæller os om praktikant () metode:

 / ** * Returnerer en kanonisk repræsentation for strengobjektet. * * En pool af strenge, oprindeligt tomme, vedligeholdes privat af * klassen {@code String}. * * Når internmetoden påberåbes, hvis puljen allerede indeholder en * streng svarende til dette {@code String} -objekt som bestemt af * metoden {@link #equals (Object)}, er strengen fra puljen * vendt tilbage. Ellers føjes dette {@code String} -objekt til * puljen, og en reference til dette {@code String} -objekt returneres. * * Det følger heraf, at for to strenge er {@code s} og {@code t} * {@code s.intern () == t.intern ()} {@code true} *, hvis og kun hvis { @code s.equals (t)} er {@code true}. * * Alle bogstavelige strenge og strengværdiansatte konstante udtryk er * interneret. Strengbogstaver er defineret i afsnit 3.10.5 i * Java ™ Language Specification. * * @ returnerer en streng, der har det samme indhold som denne streng, men som * garanteret kommer fra en pulje af unikke strenge. * @jls 3.10.5 String Literals * / public native String praktikant (); 

Det praktikant () metode bruges til at gemme Snors i en Snor pool. For det første kontrollerer det, om Snor du har oprettet, findes allerede i puljen. Hvis ikke, skaber det et nyt Snor i poolen. Bag kulisserne er logikken i Snor pooling er baseret på Flyweight-mønsteret.

Bemærk nu, hvad der sker, når vi bruger ny nøgleord for at tvinge oprettelsen af ​​to Snors:

 String hertug = ny streng ("hertug"); String duke2 = ny streng ("hertug"); System.out.println (hertug == duke2); // Resultatet vil være forkert her System.out.println (duke.intern () == duke2.intern ()); // Resultatet vil være sandt her 

I modsætning til det foregående eksempel med ny nøgleord, i dette tilfælde viser sammenligningen sig at være sand. Det skyldes, at du bruger praktikant () metode sikrer, at Snors gemmes i puljen.

Lige med metoden String-klassen

Det lige med() metoden bruges til at verificere, om tilstanden for to Java-klasser er den samme. Fordi lige med() er fra Objekt klasse, hver Java-klasse arver den. Men lige med() metoden skal tilsidesættes for at få den til at fungere korrekt. Selvfølgelig, Snor tilsidesætter lige med().

Se:

 public boolean er lig med (Object anObject) {if (this == anObject) {return true; } if (anObject instance of String) {String aString = (String) anObject; hvis (coder () == aString.coder ()) {return erLatin1 ()? StringLatin1.equals (værdi, aString.value): StringUTF16.equals (værdi, aString.value); }} returner falsk; } 

Som du kan se, tilstanden af Snor klasseværdi skal være lige med() og ikke objektreferencen. Det betyder ikke noget, om objektreferencen er anderledes; tilstanden af Snor vil blive sammenlignet.

Mest almindelige strengmetoder

Der er kun en sidste ting, du har brug for at vide, før du tager Snor sammenligningsudfordring. Overvej disse almindelige metoder til Snor klasse:

 // Fjerner mellemrum fra kanterne trim () // Får en understreng efter indekserer understreng (int begynderIndex, int slutIndex) // Returnerer tegnlængden på strenglængden () // Erstatter streng, regex kan bruges. replaceAll (String regex, String replacement) // Kontrollerer, om der er en specificeret CharSequence i String indeholder (CharSequences) 

Tag streng sammenligning udfordring!

Lad os prøve, hvad du har lært om Snor klasse i en hurtig udfordring.

Til denne udfordring sammenligner du et antal Snors bruger de koncepter, vi har udforsket. Ser du på koden nedenfor, kan du bestemme den endelige værdi for hver resultater variabel?

 public class ComparisonStringChallenge {public static void main (String ... doYourBest) {String result = ""; resultat + = "powerfulCode" .trim () == "powerfulCode"? "0": "1"; resultat + = "fleksibel kode" == "fleksibel kode"? "2": "3"; resultat + = ny streng ("doYourBest") == ny streng ("doYourBest")? "4": "5"; resultat + = ny streng ("noBugsProject"). lige ("noBugsProject")? "6": "7"; resultat + = ny streng ("breakYourLimits"). praktikant () == ny streng ("breakYourLimits"). praktikant ()? "8": "9"; System.out.println (resultat); }} 

Hvilket output repræsenterer den endelige værdi af resultatvariablen?

EN: 02468

B: 12469

C: 12579

D: 12568

Tjek dit svar her.

Hvad skete der lige? Forståelse af strengadfærd

I den første linje i koden ser vi:

 resultat + = "powerfulCode" .trim () == "powerfulCode"? "0": "1"; 

Selvom Snor vil være den samme efter trimme() metode påberåbes, Snor“Kraftfuld kode” var anderledes i starten. I dette tilfælde er sammenligningen falsk, fordi når trimme() metode fjerner mellemrum fra grænserne, det tvinger oprettelsen af ​​et nyt Snor med den nye operatør.

Dernæst ser vi:

 resultat + = "fleksibel kode" == "fleksibel kode"? "2": "3"; 

Intet mysterium her Snors er de samme i Snor pool. Denne sammenligning vender tilbage rigtigt.

Dernæst har vi:

 resultat + = ny streng ("doYourBest") == ny streng ("doYourBest")? "4": "5"; 

Bruger ny reserveret nøgleord tvinger oprettelsen af ​​to nye Snors, uanset om de er ens eller ikke. I dette tilfælde vil sammenligningen være falsk selvom den Snor værdier er de samme.

Næste er:

 resultat + = ny streng ("noBugsProject"). lige ("noBugsProject")? "6": "7"; 

Fordi vi har brugt lige med() metode, værdien af Snor vil blive sammenlignet og ikke objektforekomsten. I så fald betyder det ikke noget, om objekterne er forskellige, fordi værdien sammenlignes. Denne sammenligning vender tilbage rigtigt.

Endelig har vi:

 resultat + = ny streng ("breakYourLimits"). praktikant () == ny streng ("breakYourLimits"). praktikant ()? "8": "9"; 

Som du har set før, praktikant () metode sætter Snor i Snor pool. Begge Snors peger på det samme objekt, så i dette tilfælde er sammenligningen rigtigt.

Video udfordring! Fejlfinding af strengesammenligninger

Fejlfinding er en af ​​de nemmeste måder til fuldt ud at absorbere programmeringskoncepter, samtidig med at du forbedrer din kode. I denne video kan du følge med, mens jeg fejler og forklarer Java Strings-udfordringen:

Almindelige fejl med strenge

Det kan være svært at vide, om to Snors peger på det samme objekt, især når Snors indeholder den samme værdi. Det hjælper med at huske at bruge det reserverede nøgleord ny resulterer altid i, at der oprettes et nyt objekt i hukommelsen, selvom værdierne er de samme.

Ved brug af Snor metoder til sammenligning Objekt referencer kan også være vanskelige. Nøglen er, hvis metoden ændrer noget i Snorvil objektreferencer være forskellige.

Et par eksempler, der hjælper med at afklare:

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

Denne sammenligning vil være sand, fordi trimme() metoden genererer ikke en ny Snor.

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

I dette tilfælde den første trimme() metode genererer en ny Snor fordi metoden udfører sin handling, så referencerne vil være forskellige.

Endelig hvornår trimme() udfører sin handling, skaber den en ny Snor:

 // Implementering af trimmetoden i String-klassen ny String (Arrays.copyOfRange (val, index, index + len), LATIN1); 

Hvad man skal huske om strenge

  • Snors er uforanderlige, så a SnorTilstand kan ikke ændres.
  • For at spare hukommelse holder JVM det Snors i en Snor pool. Når en ny Snor oprettes, kontrollerer JVM værdien og peger den på et eksisterende objekt. Hvis der ikke er nogen Snor med denne værdi i puljen, opretter JVM en ny Snor.
  • Bruger == operatøren sammenligner objektreferencen. Bruger lige med() metode sammenligner værdien af Snor. Den samme regel anvendes på alle objekter.
  • Når du bruger ny operatør, en ny Snor vil blive oprettet i Snor pool, selvom der er en Snor med samme værdi.

 

Svar nøgle

Svaret på denne Java-udfordrer er Option D. Output ville være 12568.

Denne historie, "String comparisons in Java" blev oprindeligt udgivet af JavaWorld.