I Java er String
klasse innkapsler en rekke røye
. Enkelt sagt, String
er en rekke tegn som brukes til å komponere ord, setninger eller andre data du vil ha.
Innkapsling er et av de kraftigste begrepene innen objektorientert programmering. På grunn av innkapsling trenger du ikke vite det hvordan String-klassen fungerer; du trenger bare å vite hva metoder å bruke på grensesnittet.
Når du ser på String
klasse i Java, kan du se hvordan matrisen av røye
er innkapslet:
public String (char value []) {this (value, 0, value.length, null); }
For å forstå innkapsling bedre, bør du vurdere et fysisk objekt: en bil. Trenger du å vite hvordan bilen fungerer under panseret for å kjøre den? Selvfølgelig ikke, men du trenger å vite hva grensesnittene til bilen gjør: ting som gasspedal, bremser og ratt. Hver av disse grensesnittene støtter visse handlinger: akselerere, bremse, vri til venstre, ta til høyre. Det er det samme i objektorientert programmering.
Min første blogg i Java Challengers serien introduserte metoden overbelastning, som er en teknikk den String
klasse bruker mye. Overbelastning kan gjøre klassene dine veldig fleksible, inkludert String
:
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 length, String charsetName) {} // Og så videre ... ...
Snarere enn å prøve å forstå hvordan String
klassen fungerer, vil denne Java Challenger hjelpe deg med å forstå hva det gjør og hvordan å bruke den i koden din.
Hva er et strengbasseng?
String
er muligens den mest brukte klassen i Java. Hvis et nytt objekt ble opprettet i hukommelsesbunken hver gang vi brukte en String
, vi vil kaste bort mye minne. De String
basseng løser dette problemet ved å lagre bare ett objekt for hver String
verdi, som vist nedenfor.
Selv om vi opprettet en String
variabel for hertug
og Juggy
String
s, bare to objekter blir opprettet og lagret i minnesbunken. For bevis, se på følgende kodeeksempel. (Husk at “==
”-Operatør i Java brukes til å sammenligne to objekter og avgjøre om de er de samme.)
String juggy = "Juggy"; String anotherJuggy = "Juggy"; System.out.println (juggy == anotherJuggy);
Denne koden kommer tilbake ekte
fordi de to String
s peker på det samme objektet i String
basseng. Verdiene deres er de samme.
Et unntak: Den ‘nye’ operatøren
Se nå på denne koden - den ser ut som den forrige prøven, men det er en forskjell.
String hertug = ny streng ("hertug"); String anotherDuke = ny streng ("hertug"); System.out.println (hertug == anotherDuke);
Basert på forrige eksempel, kan du tro at denne koden ville komme tilbake ekte
, men det er faktisk falsk
. Legge til ny
operatøren tvinger etableringen av en ny String
i minnehaugen. Dermed vil JVM lage to forskjellige objekter.
Innfødte metoder
EN innfødt metode i Java er en metode som skal kompileres ved hjelp av C-språket, vanligvis med det formål å manipulere minne og optimalisere ytelsen.
Strengbassenger og intern () -metoden
Å lagre en String
i String
basseng, bruker vi en teknikk som heter String
interning. Her er hva Javadoc forteller oss om turnuskandidat()
metode:
/ ** * Returnerer en kanonisk representasjon for strengobjektet. * * Et basseng med strenger, først tomt, vedlikeholdes privat av * klassen {@code String}. * * Når internmetoden påkalles, hvis bassenget allerede inneholder en * streng lik dette {@code String} -objektet som bestemt av * metoden {@link #equals (Object)}, er strengen fra bassenget returnert. Ellers blir dette {@code String} -objektet lagt til i * bassenget, og en referanse til dette {@code String} -objektet returneres. * * Det følger at for to strenger {@code s} og {@code t}, er * {@code s.intern () == t.intern ()} {@code true} * hvis og bare hvis { @code s.equals (t)} er {@code true}. * * Alle bokstavelige strenger og strengverdige konstante uttrykk er * internert. Strengbokstaver er definert i avsnitt 3.10.5 i * Java ™ språkspesifikasjonen. * * @ returnerer en streng som har samme innhold som denne strengen, men som * garantert kommer fra en samling unike strenger. * @jls 3.10.5 String Literals * / public native String intern ();
De turnuskandidat()
metoden brukes til å lagre String
s i en String
basseng. Først verifiserer det om String
du har opprettet, eksisterer allerede i bassenget. Hvis ikke, skaper det et nytt String
i bassenget. Bak kulissene, logikken til String
pooling er basert på Flyweight-mønsteret.
Legg merke til hva som skjer når vi bruker ny
nøkkelord for å tvinge opprettelsen av to String
s:
String hertug = ny streng ("hertug"); String duke2 = new String ("duke"); System.out.println (hertug == duke2); // Resultatet vil være falskt her System.out.println (duke.intern () == duke2.intern ()); // Resultatet vil være sant her
I motsetning til forrige eksempel med ny
nøkkelord, i dette tilfellet viser sammenligningen seg å være sant. Det er fordi bruk av turnuskandidat()
metoden sikrer String
s lagres i bassenget.
Ligner metode med String-klassen
De er lik()
metoden brukes til å verifisere om tilstanden til to Java-klasser er den samme. Fordi er lik()
er fra Gjenstand
klasse, arver hver Java-klasse den. Men er lik()
metoden må overstyres for å få den til å fungere skikkelig. Selvfølgelig, String
overstyrer er lik()
.
Ta en titt:
offentlig boolsk er lik (Object anObject) {if (this == anObject) {return true; } if (anObject instance of String) {String aString = (String) anObject; hvis (coder () == aString.coder ()) {return erLatin1 ()? StringLatin1.equals (verdi, aString.value): StringUTF16.equals (verdi, aString.value); }} returner falsk; }
Som du kan se, er tilstanden til String
klasseverdien må være er lik()
og ikke objektreferansen. Det spiller ingen rolle om objektreferansen er annerledes; tilstanden til String
vil bli sammenlignet.
De vanligste strengmetodene
Det er bare en siste ting du trenger å vite før du tar String
sammenligningsutfordring. Vurder disse vanlige metodene for String
klasse:
// Fjerner mellomrom fra kantlinjene () // Får en delstreng ved å indeksere delstreng (int beginIndex, int endIndex) // Returnerer tegnlengden på strenglengden () // Erstatter streng, regex kan brukes. replaceAll (String regex, String replacement) // Bekrefter om det er en spesifisert CharSequence i Strengen inneholder (CharSequences)
Ta String sammenligningsutfordringen!
La oss prøve det du har lært om String
klasse i en rask utfordring.
For denne utfordringen vil du sammenligne et antall String
s bruker konseptene vi har utforsket. Ser du på koden nedenfor, kan du bestemme den endelige verdien av hver resultater variabel?
public class ComparisonStringChallenge {public static void main (String ... doYourBest) {String result = ""; resultat + = "powerfulCode" .trim () == "powerfulCode"? "0": "1"; resultat + = "FlexibleCode" == "FlexibleCode"? "2": "3"; resultat + = ny streng ("gjørDinBest") == ny streng ("gjørDinBest")? "4": "5"; resultat + = ny streng ("noBugsProject"). likestillinger ("noBugsProject")? "6": "7"; resultat + = ny streng ("breakYourLimits"). praktikant () == ny streng ("breakYourLimits"). praktikant ()? "8": "9"; System.out.println (resultat); }}
Hvilken utgang representerer den endelige verdien av resultatvariabelen?
EN: 02468
B: 12469
C: 12579
D: 12568
Sjekk svaret ditt her.
Hva skjedde nå? Forstå strengadferd
I den første linjen i koden ser vi:
resultat + = "powerfulCode" .trim () == "powerfulCode"? "0": "1";
Selv om String
vil være den samme etter listverk()
metoden påberopes, String
“Kraftig kode”
var annerledes i begynnelsen. I dette tilfellet er sammenligningen falsk
, fordi når listverk()
metoden fjerner mellomrom fra grensene den tvinger etableringen av et nytt String
med den nye operatøren.
Deretter ser vi:
resultat + = "FlexibleCode" == "FlexibleCode"? "2": "3";
Ingen mysterium her, den String
s er de samme i String
basseng. Denne sammenligningen kommer tilbake ekte
.
Deretter har vi:
resultat + = ny streng ("gjørDinBest") == ny streng ("gjørDinBest")? "4": "5";
Bruker ny
reservert nøkkelord tvinger etableringen av to nye String
s, enten de er like eller ikke. I dette tilfellet vil sammenligningen være falsk
selv om String
verdiene er de samme.
Neste er:
resultat + = ny streng ("noBugsProject"). likestillinger ("noBugsProject")? "6": "7";
Fordi vi har brukt er lik()
metoden, verdien av String
vil bli sammenlignet og ikke objektforekomsten. I så fall spiller det ingen rolle om objektene er forskjellige fordi verdien blir sammenlignet. Denne sammenligningen kommer tilbake ekte
.
Til slutt har vi:
resultat + = ny streng ("breakYourLimits"). praktikant () == ny streng ("breakYourLimits"). praktikant ()? "8": "9";
Som du har sett før, turnuskandidat()
metoden setter String
i String
basseng. Både String
s peker på det samme objektet, så i dette tilfellet er sammenligningen ekte
.
Videoutfordring! Feilsøking av streng sammenligninger
Feilsøking er en av de enkleste måtene å fullt ut absorbere programmeringskonsepter samtidig som du forbedrer koden din. I denne videoen kan du følge med mens jeg feilsøker og forklarer Java Strings-utfordringen:
Vanlige feil med strenger
Det kan være vanskelig å vite om to String
s peker på det samme objektet, spesielt når String
s inneholder samme verdi. Det hjelper å huske at bruk av det reserverte nøkkelordet ny
resulterer alltid i at et nytt objekt blir opprettet i minnet, selv om verdiene er de samme.
Ved hjelp av String
metoder for å sammenligne Gjenstand
referanser kan også være vanskelig. Nøkkelen er, hvis metoden endrer noe i String
vil objektreferansene være forskjellige.
Noen få eksempler for å avklare:
System.out.println ("hertug" .trim () == "hertug" .trim ()) ;;
Denne sammenligningen vil være sant fordi listverk()
metoden genererer ikke en ny String
.
System.out.println ("hertug" .trim () == "hertug" .trim ());
I dette tilfellet den første listverk()
metoden vil generere en ny String
fordi metoden vil utføre sin handling, så referansene vil være forskjellige.
Endelig når listverk()
utfører sin handling, skaper den en ny String
:
// Implementering av trimmetoden i String-klassen new String (Arrays.copyOfRange (val, index, index + len), LATIN1);
Hva du skal huske om strenger
String
s er uforanderlige, så aString
Tilstand kan ikke endres.- For å spare minne holder JVM
String
s i enString
basseng. Når en nyString
blir opprettet, sjekker JVM verdien og peker den mot et eksisterende objekt. Hvis det ikke er noeString
med den verdien i bassenget, oppretter JVM en nyString
. - Bruker
==
operatøren sammenligner objektreferansen. Brukerer lik()
metoden sammenligner verdien avString
. Den samme regelen blir brukt på alle objekter. - Når du bruker
ny
operatør, en nyString
vil bli opprettet iString
basseng selv om det er etString
med samme verdi.
Fasit
Svaret på denne Java-utfordreren er alternativ D. Utgangen ville være 12568
.
Denne historien, "String comparisons in Java" ble opprinnelig utgitt av JavaWorld.