Allan wrote:
> Jeg har sat en println ind som skriver
> det ud den modtager og den skriver lige så pænt et a, men når jeg laver en
> if (input == "a"), så går den ikke ind i if-sætningen.
Hvert nyt objekt der oprettes i Java får tildelt et unikt /objektid/.
Når du skriver
String input = "hejsa"
så oprettes der et objekt i systemet, og "input" får tildelt en
/objektreference/ (i form af føromtalte objektid) til objektet.
Når du skriver "a == b" så undersøges der om objektreferencerne peger på
det samme objekt, dvs. der testes for /fysisk identitet/. Med andre ord
så vil
if (input == "a")
kun fungere såfremt "input" og '"a"' har samme objektreference - også
selvom "input" rent faktisk repræsenterer bogstavet "a".
Hvis du har to objekter af samme klassetype og som ikke er fysisk
identiske, så kan man teste for /logisk identitet/, dvs. vha. en metode,
der sammenligner attributterne. I Java bruger man pr. konvention
"equals"-metoden, som man selv har ansvar for at implementere i nye
klasser.
Du kan f.eks. bruge
if (("a").equals(input))
som også fungerer selvom "input" antager null-værdien.
En anden måde (som ikke fungerer, hvis "input" er null) er
if (input.intern() == "a")
Bemærk at vi her bruger "=="-operatoren!
Årsagen til at vi kan teste for fysisk identitet er at String-klassen
vedligeholder en intern pulje over strenge. Kalder du intern() på et
String-objekt og findes det ikke i puljen i forvejen, så bliver det
tilføjet og dets objektreference bliver returneret. Hvis puljen allerede
indeholder en streng som er logisk identisk (dvs. der testes vha.
"equals"-metoden) så returneres en objektreference til denne streng.
Initielt bliver alle strenge som kan bestemmes på compile time indsat i
puljen, mens nye objekter kun ryger deri såfremt deres "intern"-metode
bliver kaldt. Det har ganske interessante konsekvenser.
Min påstand er at nedenstående kode altid vil udskrive "Hej med dig" til
trods for at vi tester for fysisk identitet uden at inddrage
"intern"-metoden.
String foo = "Hej ";
String bar = "med dig";
String foobar = foo+bar;
if (foobar == "Hej med dig") {
System.out.println(foobar);
}
Hvis "foobar" derimod bliver bestemt på runtime, f.eks. ved at brugeren
indtaster en værdi, så vil det ikke fungere uanset om denne værdi måtte
være "Hej med dig" da der pludselig er tale om forskellige
objektreferencer!
Du kan læse om det i Java Language Specification, §3.10.5
(
http://java.sun.com/docs/books/jls/second_edition/html/lexical.doc.html)
Morale: Bruge altid "equals"- eller "intern"-metoden når du skal
sammenligne strenge.
--
Jonas Kongslund,
http://kongslund.dk