Programmering

Går Java forbi reference eller passerer værdi?

Mange programmeringssprog tillader videregivelse af parametre ved reference eller efter værdi. I Java kan vi kun videregive parametre efter værdi. Dette lægger nogle grænser og rejser også spørgsmål. For eksempel, hvis parameterværdien ændres i metoden, hvad sker der med værdien efter metodeudførelse? Du kan også undre dig over, hvordan Java administrerer objektværdier i hukommelsesbunken. Det her Java Challenger hjælper dig med at løse disse og andre almindelige spørgsmål om objektreferencer i Java.

Få kildekoden

Få koden til denne Java Challenger. Du kan køre dine egne tests, mens du følger eksemplerne.

Objektreferencer sendes efter værdi

Alle objektreferencer i Java sendes efter værdi. Dette betyder, at en kopi af værdien overføres til en metode. Men tricket er, at videregivelse af en kopi af værdien også ændrer den reelle værdi af objektet. For at forstå hvorfor skal du starte med dette eksempel:

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

Hvad tror du simpson.name vil være efter transformer IntoHomer metode udføres?

I dette tilfælde vil det være Homer! Årsagen er, at Java-objektvariabler simpelthen er referencer, der peger på rigtige objekter i hukommelsesbunken. Derfor, selvom Java sender parametre til metoder efter værdi, ændres det virkelige objekt også, hvis variablen peger på en objektreference.

Hvis du stadig ikke er helt klar over, hvordan dette fungerer, skal du se på nedenstående figur.

Rafael Chinelato Del Nero

Overføres primitive typer med værdi?

Ligesom objekttyper overføres også primitive typer med værdi. Kan du udlede, hvad der vil ske med de primitive typer i følgende kodeeksempel?

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

Hvis du har bestemt, at værdien vil ændre sig til 30, er du korrekt. Det er 30, fordi (igen) Java overfører objektparametre efter værdi. Tallet 30 er kun en kopi af værdien, ikke den reelle værdi. Primitive typer tildeles i stakhukommelsen, så kun den lokale værdi ændres. I dette tilfælde er der ingen objektreference.

Videregivelse af uforanderlige objektreferencer

Hvad hvis vi gjorde den samme test med en uforanderlig Snor objekt?

JDK indeholder mange uforanderlige klasser. Eksempler inkluderer indpakningstyperne Heltal, Dobbelt, Flyde, Lang, Boolsk, BigDecimal, og selvfølgelig det meget velkendte Snor klasse.

I det næste eksempel skal du bemærke, hvad der sker, når vi ændrer værdien af ​​a Snor.

 offentlig klasse StringValueChange {public static void main (String ... doYourBest) {String name = ""; changeToHomer (navn); System.out.println (navn); } statisk tomrumsændringToHomer (strengnavn) {name = "Homer"; }} 

Hvad tror du output vil være? Hvis du gættede “” så tillykke! Det sker, fordi en Snor genstand er uforanderligt, hvilket betyder, at felterne inde i Snor er endelige og kan ikke ændres.

At lave Snor klasse uforanderlig giver os bedre kontrol over et af Java mest anvendte objekter. Hvis værdien af ​​en Snor kunne ændres, ville det skabe mange bugs. Bemærk også, at vi ikke ændrer en attribut for Snor klasse; i stedet tildeler vi simpelthen en ny Snor værdi for det. I dette tilfælde overføres "Homer" -værdien til navn i ændreToHomer metode. Det Snor "Homer" er berettiget til at blive indsamlet skrald, så snart ændreToHomer metoden fuldender udførelsen. Selvom objektet ikke kan ændres, vil den lokale variabel være.

Strenge og mere

Lær mere om Java'er Snor klasse og mere: Se alle Rafaels indlæg i Java Challengers-serien.

Videregivelse af mutable objekthenvisninger

I modsætning til Snor, de fleste objekter i JDK kan ændres, ligesom StringBuilder klasse. Eksemplet nedenfor ligner det forrige, men har funktioner StringBuilder hellere end Snor:

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

Kan du udlede output til dette eksempel? I dette tilfælde vil output være "Homer Simpson", fordi vi arbejder med et mutabelt objekt. Du kan forvente den samme adfærd fra ethvert andet ændret objekt i Java.

Du har allerede lært, at Java-variabler videregives efter værdi, hvilket betyder, at en kopi af værdien videregives. Husk bare, at den kopierede værdi peger på a ægte objekt i Java-hukommelsesbunken. At passere værdi ændrer stadig værdien af ​​det virkelige objekt.

Tag udfordringen med objektreferencer!

I denne Java Challenger vil vi teste, hvad du har lært om objektreferencer. I kodeeksemplet nedenfor ser du det uforanderlige Snor og det ændrede StringBuilder klasse. Hver overføres som en parameter til en metode. Når du ved, at Java kun passerer værdi, hvad tror du vil være output, når hovedmetoden fra denne klasse er udført?

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

Her er mulighederne, kontroller slutningen af ​​denne artikel for svarnøglen.

EN: Kriger = null Våben = null

B: Warrior = Dragon Weapon = Dragon

C: Kriger = Dragon Knight Weapon = Dragon Sword

D: Warrior = Dragon Knight Weapon = Sword

Hvad er der lige sket?

Den første parameter i ovenstående eksempel er krigerProfession variabel, som er et ændret objekt. Den anden parameter, våben, er en uforanderlig Snor:

 statisk ugyldig ændringWarriorClass (StringBuilder warriorProfession, String våben) {...} 

Lad os nu analysere, hvad der sker inden for denne metode. På den første linje i denne metode tilføjer vi Ridder værdi til krigerProfession variabel. Huske på, at krigerProfession er et ændret objekt derfor vil det virkelige objekt blive ændret, og værdien fra det vil være "Dragon Knight."

 warriorProfession.append ("Knight"); 

I den anden instruktion, den uforanderlige lokale Snor variabel ændres til "Dragon Sword." Det virkelige objekt vil dog aldrig blive ændret siden Snor er uforanderlig og dens egenskaber er endelige:

 våben = "Dragon" + våben; 

Endelig passerer vi nul til variablerne her, men ikke til objekterne. Objekterne forbliver de samme, så længe de stadig er tilgængelige eksternt - i dette tilfælde gennem hovedmetoden. Og selvom de lokale variabler er nul, sker der intet med objekterne:

 våben = null; warriorProfession = null; 

Ud fra alt dette kan vi konkludere, at de endelige værdier fra vores mutable StringBuilder og uforanderlig Snor vil være:

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

Den eneste værdi, der ændrede sig i changeWarriorClass metoden var krigerProfession, fordi det er en ændring StringBuilder objekt. Noter det kriger Våben ændrede sig ikke, fordi det er en uforanderlig Snor objekt.

Den korrekte output fra vores Challenger-kode ville være:

D: Warrior = Dragon Knight Weapon = Sword.

Video udfordring! Fejlfinding af objektreferencer i Java

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 debugger og forklarer objektreferencer i Java.

Almindelige fejl med objektreferencer

  • Forsøger at ændre en uforanderlig værdi ved henvisning.
  • Forsøger at ændre en primitiv variabel som reference.
  • At forvente det rigtige objekt ændres ikke, når du ændrer en ændret objektparameter i en metode.

Hvad man skal huske om objektreferencer

  • Java sender altid parametervariabler efter værdi.
  • Objektvariabler i Java peger altid på det rigtige objekt i hukommelsesbunken.
  • Et ændret objekts værdi kan ændres, når det overføres til en metode.
  • Et uforanderligt objekts værdi kan ikke ændres, selvom det får en ny værdi.
  • "At passere værdi" henviser til at sende en kopi af værdien.
  • "At videregive ved henvisning" henviser til at videregive den reelle reference til variablen i hukommelsen.

Lær mere om Java

  • Få flere hurtige kodetip: Læs alle Rafaels indlæg i JavaWorld Java Challengers-serien.
  • Lær mere om ændrede og uforanderlige Java-objekter (f.eks Snor og StringBuffer) og hvordan man bruger dem i din kode.
  • Du kan blive overrasket over at høre, at Java's primitive typer er kontroversielle. I denne funktion gør John I. Moore argument for at beholde dem og lære at bruge dem godt.
  • Fortsæt med at opbygge dine Java-programmeringsevner i Java Dev Gym.
  • Hvis du kunne lide fejlfinding af Java-arv, skal du tjekke flere videoer i Rafaels Java-udfordringer-videoafspilningsliste (videoer i denne serie er ikke tilknyttet JavaWorld).
  • Vil du arbejde på stressfrie projekter og skrive fejlfri kode? Gå over til NoBugsProject for din kopi af Ingen fejl, ingen stress - Opret livsændrende software uden at ødelægge dit liv.

Denne historie, "Går Java efter reference eller passerer værdi?" blev oprindeligt udgivet af JavaWorld.

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