Kun pilkon esim seuraavan merkkijonon osiin split metodilla, niin saatuja merkkijonoja verratessa ne eivät täsmää itsensä kanssa näennäisesti identtisiin merkkijonoihin.
String[] x = "eka toka".split("\\s");
Nyt siis jos tulostan x[1] sisällön näytölle, niin näkyviin tulee ihan oikein "toka", mutta jos vertaan (x[1] == "toka"), niin tuo ei pidäkkään paikkaansa.
Mistä tuo johtuu tai mitä olen missannut?
Käytä merkkijonojen vertailuun equals-metodia. ==-operaattori vertailee vain sitä ovatko oliot samoja, ei sitä onko niiden sisältö "sama".
Esimerkkejä:
String a = "foo"; String b = "foo"; String c = a; String d = "bar"; if (a == b) { // Palauttaa false, koska a ja b ovat eri olioita. } if (a == c) { // Palauttaa true, koska a ja b ovat viittaukset samaan olioon. } if (a.equals(b)) { // Palauttaa true, koska "foo" on yhtä kuin "foo". } if (a.equals(c)) { // Palauttaa true, koska "foo" on yhtä kuin "foo". } if (a.equals(d)) { // Palauttaa false, koska "foo" ei ole sama kuin "bar". }
Dodii, kiitos.
Sami kirjoitti:
String a = "foo"; String b = "foo"; if (a == b) { // Palauttaa false, koska a ja b ovat eri olioita. }
Paitsi kun merkkijonovakiot on määritelty saman luokan sisällä. Silloin kääntäjä optimoi, että molemmat vakiot ovat viitteitä samaan olioon. Jos Stringit tuotetaan dynaamisesti (esim. new String("foo") tai mainittu split-metodi), niin sitten ne ovat oikeasti eri olioita. Eli joskus == voi sattumalta toimia, mutta siihen ei pidä koskaan luottaa.
Jackal von ÖRF kirjoitti:
Sami kirjoitti:
String a = "foo"; String b = "foo"; if (a == b) { // Palauttaa false, koska a ja b ovat eri olioita. }Paitsi kun merkkijonovakiot on määritelty saman luokan sisällä. Silloin kääntäjä optimoi, että molemmat vakiot ovat viitteitä samaan olioon. Jos Stringit tuotetaan dynaamisesti (esim. new String("foo") tai mainittu split-metodi), niin sitten ne ovat oikeasti eri olioita. Eli joskus == voi sattumalta toimia, mutta siihen ei pidä koskaan luottaa.
Ei taida olla suoranaisesti kääntäjän optimointi vaan java virtuaalikoneen käyttämän String toteutuksen ominaisuus. Java käyttää Stringien optimoimiseen string pool toteusta eli ohjelmassa esiintyvät merkkijonovakiot taulukoidaan, jotta samanlaiselle merkkijonolle voidaan antaa sama muistiosoite. Myös itsemuodostetut merkkijonot voidaan lisätä pooliin String-luokan intern()-metodilla.
Esim.
String f = "foo"; String b = "bar"; String fb = "foobar"; System.out.println(f+b == fb); System.out.println((f+b).intern() == fb);
Yleisesti siis kannattaa kuitenkin käyttää equals()-metodia merkkijonojen vertailuun. Ainoa huono puoli siinä tosin on, että pitää aina muistaa erikseen tarkistaa, että ensimmäinen vertailtava merkkijono ei ole null.
Tietyissä tilanteissa kuitenkin intern():n käyttö on ihan hyvä optimoitikikka muistinkulutuksen ja nopeuden suhteen (voidaan käyttää == operaattoria, kun kaikki samanlaiset merkkijonot ovat oikeasti samassa osoitteessa.)
String: intern() kirjoitti:
Returns a canonical representation for the string object.
A pool of strings, initially empty, is maintained privately by the class String.
When the intern method is invoked, if the pool already contains a string equal to this String object as determined by the equals(Object) method, then the string from the pool is returned. Otherwise, this String object is added to the pool and a reference to this String object is returned.
It follows that for any two strings s and t, s.intern() == t.intern() is true if and only if s.equals(t) is true.
All literal strings and string-valued constant expressions are interned. String literals are defined in §3.10.5 of the Java Language Specification
Aihe on jo aika vanha, joten et voi enää vastata siihen.