Programmering

Passer Java etter referanse eller passerer verdi?

Mange programmeringsspråk tillater overføring av parametere ved referanse eller etter verdi. I Java kan vi bare overføre parametere etter verdi. Dette setter noen grenser og reiser også spørsmål. For eksempel, hvis parameterverdien endres i metoden, hva skjer med verdien etter metodeutførelsen? Du kan også lure på hvordan Java håndterer objektverdier i hukommelsen. Dette Java Challenger hjelper deg med å løse disse og andre vanlige spørsmål om objektreferanser i Java.

Få kildekoden

Få koden for denne Java Challenger. Du kan kjøre dine egne tester mens du følger eksemplene.

Objektreferanser sendes etter verdi

Alle objektreferanser i Java sendes etter verdi. Dette betyr at en kopi av verdien vil bli sendt til en metode. Men trikset er at å sende en kopi av verdien også endrer den virkelige verdien av objektet. For å forstå hvorfor, start med dette eksemplet:

 public class ObjectReferenceExample {public static void main (String ... doYourBest) {Simpson simpson = new Simpson (); transformIntoHomer (simpson); System.out.println (simpson.name); } statisk tomrom transformIntoHomer (Simpson simpson) {simpson.name = "Homer"; }} klasse Simpson {Strengnavn; } 

Hva tror du simpson.name vil være etter transformIntoHomer metoden er utført?

I dette tilfellet blir det Homer! Årsaken er at Java-objektvariabler rett og slett er referanser som peker på virkelige objekter i minnesbunken. Derfor, selv om Java overfører parametere til metoder etter verdi, vil variabelen peke på en objektreferanse også endres.

Hvis du fremdeles ikke er helt klar over hvordan dette fungerer, kan du ta en titt på figuren nedenfor.

Rafael Chinelato Del Nero

Passeres primitive typer etter verdi?

Som objekttyper passeres også primitive typer etter verdi. Kan du utlede hva som vil skje med de primitive typene i følgende kodeeksempel?

 public class PrimitiveByValueExample {public static void main (String ... primitiveByValue) {int homerAge = 30; changeHomerAge (homerAge); System.out.println (homerAge); } statisk tomrom endringHomerAge (int homerAge) {homerAge = 35; }} 

Hvis du bestemte deg for at verdien ville endres til 30, har du rett. Det er 30 fordi (igjen) Java overfører objektparametere etter verdi. Tallet 30 er bare en kopi av verdien, ikke den virkelige verdien. Primitive typer er tildelt i stackminnet, så bare den lokale verdien vil bli endret. I dette tilfellet er det ingen objektreferanse.

Passerer uforanderlige objektreferanser

Hva om vi gjorde den samme testen med en uforanderlig String gjenstand?

JDK inneholder mange uforanderlige klasser. Eksempler inkluderer innpakningstyper Heltall, Dobbelt, Flyte, Lang, Boolsk, BigDecimal, og selvfølgelig de veldig kjente String klasse.

Legg merke til hva som skjer når vi endrer verdien på et i neste eksempel String.

 public class StringValueChange {public static void main (String ... doYourBest) {String name = ""; endreToHomer (navn); System.out.println (navn); } statisk ugyldig endringToHomer (strengnavn) {name = "Homer"; }} 

Hva tror du produksjonen vil være? Hvis du gjettet “” så gratulerer! Det skjer fordi en String objektet er uforanderlig, noe som betyr at feltene inne i String er endelige og kan ikke endres.

Å lage String klasse uforanderlig gir oss bedre kontroll over et av Java mest brukte objekter. Hvis verdien av en String kunne endres, ville det skape mange feil. Vær også oppmerksom på at vi ikke endrer et attributt av String klasse; i stedet tildeler vi ganske enkelt en ny String verdi for det. I dette tilfellet vil "Homer" -verdien overføres til Navn i changeToHomer metode. De String "Homer" vil være kvalifisert til å bli samlet inn søppel så snart endreToHomer metoden fullfører utførelsen. Selv om objektet ikke kan endres, vil den lokale variabelen være det.

Strenger og mer

Lær mer om Java-er String klasse og mer: Se alle Rafaels innlegg i Java Challengers-serien.

Passerer mutable objektreferanser

I motsetning til String, de fleste objekter i JDK er mutable, som StringBuilder klasse. Eksemplet nedenfor ligner på det forrige, men har funksjoner StringBuilder heller enn String:

 statisk klasse MutableObjectReference {public static void main (String ... mutableObjectExample) {StringBuilder name = new StringBuilder ("Homer"); addSureName (navn); System.out.println (navn); } statisk tomrom addSureName (StringBuilder navn) {name.append ("Simpson"); }} 

Kan du trekke ut resultatet for dette eksemplet? I dette tilfellet, fordi vi jobber med et foranderlig objekt, vil utdataene være "Homer Simpson." Du kan forvente den samme oppførselen fra alle andre mutable objekter i Java.

Du har allerede lært at Java-variabler sendes etter verdi, noe som betyr at en kopi av verdien sendes. Bare husk at den kopierte verdien peker på a ekte gjenstand i Java-minnehaugen. Å gå forbi verdi endrer fortsatt verdien på det virkelige objektet.

Ta objektreferansene utfordring!

I denne Java Challenger vil vi teste hva du har lært om objektreferanser. I kodeeksemplet nedenfor ser du det uforanderlige String og det foranderlige StringBuilder klasse. Hver overføres som parameter til en metode. Å vite at Java bare passerer verdi, hva tror du vil være utdata når hovedmetoden fra denne klassen er utført?

 offentlig klasse DragonWarriorReferenceChallenger {public static void main (String ... doYourBest) {StringBuilder warriorProfession = new StringBuilder ("Dragon"); String warriorWeapon = "Sverd"; changeWarriorClass (warriorProfession, warriorWeapon); System.out.println ("Warrior =" + warriorProfession + "Weapon =" + warriorWeapon); } statisk ugyldig endringWarriorClass (StringBuilder warriorProfession, String våpen) {warriorProfession.append ("Knight"); våpen = "Dragon" + våpen; våpen = null; warriorProfession = null; }} 

Her er alternativene, sjekk slutten av denne artikkelen for svarnøkkelen.

EN: Kriger = null Våpen = null

B: Warrior = Dragon Weapon = Dragon

C: Warrior = Dragon Knight Weapon = Dragon Sword

D: Kriger = Dragon Knight Weapon = Sverd

Hva har nettopp skjedd?

Den første parameteren i eksemplet ovenfor er warriorProfession variabel, som er et foranderlig objekt. Den andre parameteren, våpen, er en uforanderlig String:

 statisk tomromendringWarriorClass (StringBuilder warriorProfession, String våpen) {...} 

La oss nå analysere hva som skjer i denne metoden. På første linje i denne metoden legger vi til Ridder verdi til warriorProfession variabel. Husk at warriorProfession er et foranderlig objekt; derfor vil den virkelige gjenstanden endres, og verdien fra den vil være "Dragon Knight."

 warriorProfession.append ("Knight"); 

I den andre instruksjonen, den uforanderlige lokale String variabel vil bli endret til "Dragon Sword." Det virkelige objektet vil imidlertid aldri bli endret siden String er uforanderlig og dens egenskaper er endelige:

 våpen = "Dragon" + våpen; 

Til slutt passerer vi null til variablene her, men ikke til objektene. Objektene vil forbli de samme så lenge de fremdeles er tilgjengelige eksternt - i dette tilfellet gjennom hovedmetoden. Og selv om de lokale variablene vil være null, vil ingenting skje med objektene:

 våpen = null; warriorProfession = null; 

Fra alt dette kan vi konkludere med at de endelige verdiene fra vår mutable StringBuilder og uforanderlig String vil være:

 System.out.println ("Warrior =" + warriorProfession + "Weapon =" + warriorWeapon); 

Den eneste verdien som endret seg i endreWarriorClass metoden var warriorProfession, fordi det er en foranderlig StringBuilder gjenstand. Noter det warriorWeapon endret seg ikke fordi det er en uforanderlig String gjenstand.

Den riktige utgangen fra Challenger-koden vår vil være:

D: Kriger = Dragon Knight Weapon = Sverd.

Videoutfordring! Feilsøking av objektreferanser i Java

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 objektreferanser i Java.

Vanlige feil med objektreferanser

  • Prøver å endre en uforanderlig verdi ved referanse.
  • Prøver å endre en primitiv variabel ved referanse.
  • Å forvente det virkelige objektet vil ikke endres når du endrer en parameter som kan endres i en metode.

Hva du skal huske om objektreferanser

  • Java overfører alltid parametervariabler etter verdi.
  • Objektvariabler i Java peker alltid på det virkelige objektet i hukommelsen.
  • Verdien til et foranderlig objekt kan endres når det overføres til en metode.
  • Verdien til et uforanderlig objekt kan ikke endres, selv om det får en ny verdi.
  • "Å passere etter verdi" refererer til å sende en kopi av verdien.
  • "Passing by reference" refererer til å sende den reelle referansen til variabelen i minnet.

Lær mer om Java

  • Få flere raske kodetips: Les alle innleggene til Rafael i JavaWorld Java Challengers-serien.
  • Lær mer om foranderlige og uforanderlige Java-objekter (for eksempel String og StringBuffer) og hvordan du bruker dem i koden din.
  • Du kan bli overrasket over å høre at Java's primitive typer er kontroversielle. I denne funksjonen gjør John I. Moore saken for å beholde dem, og lære å bruke dem godt.
  • Fortsett å bygge Java-programmeringsferdighetene dine i Java Dev Gym.
  • Hvis du likte feilsøking av Java-arv, kan du sjekke ut flere videoer i Rafaels Java-utfordringer-videospilleliste (videoer i denne serien er ikke tilknyttet JavaWorld).
  • Vil du jobbe med stressfrie prosjekter og skrive feilfri kode? Gå over til NoBugsProject for din kopi av Ingen feil, ingen stress - Lag livsforandrende programvare uten å ødelegge livet ditt.

Denne historien, "Passer Java etter referanse eller passerer verdi?" ble opprinnelig utgitt av JavaWorld.

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