Archief - Java, wanneer passed by reference of passed by value?

Het archief is een bevroren moment uit een vorige versie van dit forum, met andere regels en andere bazen. Deze posts weerspiegelen op geen enkele manier onze huidige ideeën, waarden of wereldbeelden en zijn op sommige plaatsen gecensureerd wegens ontoelaatbaar. Veel zijn in een andere tijdsgeest gemaakt, al dan niet ironisch - zoals in het ironische subforum Off-Topic - en zouden op dit moment niet meer gepost (mogen) worden. Toch bieden we dit archief nog graag aan als informatiedatabank en naslagwerk. Lees er hier meer over of start een gesprek met anderen.

Tw33tst3r

Legacy Member
ik volg atm een opleiding java-ontwikkelaar bij de vdab en aangezien de docent mij tot nu toe op zo goed als geen enkele vraag antwoord heeft kunnen geven dacht ik hier es een poging te wagen (andere vragen heeft google mij gelukkig wel al beantwoord)

als je een String doorgeeft stond in mijn cursus dan gebeurt dit door passing by reference en niet by value
vb.
String a = "Test";
String b = a;
b = "niet test";

dan krijgt a ook de waarde "niet test" omdat b simpelweg naar dezelfde plaats in het geheugen verwijst, hence passing by reference

mijn vraag is nu:
wat gebeurt er juist als ik bvb een object aanmaak via een constructor of een method aanroep van een object waarbij ik een variabele gebruik als String parameter?
bvb.
String type = "mountainbike";

Fiets.setType(type);

method heeft dan volgende body:
Public void setType(String type){
this.type = type;
}

als ik dan nadien in main de waarde van type verander dan verandert uiteraard de property van mijn object Fiets niet, dat is logisch qua gebruik maar op dat moment pass ik eigenlijk toch een reference variabele en niet de waarde van die String?

nu ik had al het idee dat dit kwam omdat de property type enkel binnen de class block bestaat en dat deze daarom niet verandert maar waarom dan ook niet als deze public is en bijgevolg buiten de scope van het block valt?

andere optie dak kon bedenken was dat op het moment dat de method gecalled wordt deze de waarde van de string doorgeeft maar dat spreekt dan weer mijn cursus tegen :s

is mss een stomme vraag en ik ben ondertussen ook al veel verder in mijn cursus mr ik vroeg mij dat ineens af toen ik vr de zoveelste keer een reference variabele als parameter gebruikte

Jack

Legacy Member
dit probleem komt eigenlijk alleen bij Strings voor. In Java is het simpel: primitives worden altijd by value doorgegeven, objecten altijd by reference.

Echter is een String beide... technisch gezien is een String een object, maar het is eigenlijk ook een primitive, of laat zich toch althans zo gebruiken. Ik denk dat in method calls (wat constructors in essentie ook zijn) Strings by value gepasst worden.

Cycloon

Legacy Member
Ook opletten met Integer, Double, Float, ... Bij een methode worden die ook doorgeven by value en niet by reference. Nogal vreemd natuurlijk omdat het net wrapperklassen zijn met de bedoeling om van een primitief ding een object te maken.

forloRn_

Legacy Member
Tw33tst3r zei:
vb.
String a = "Test";
String b = a;
b = "niet test";

dan krijgt a ook de waarde "niet test" omdat b simpelweg naar dezelfde plaats in het geheugen verwijst, hence passing by reference

Blijkbaar niet zo simpelweg, want dit is verkeerd. b wijst naar "niet test", terwijl a nog altijd naar "Test" wijst.

De referentie a heb je op geen enkel punt veranderd, die wijst dus nog altijd naar "Test". b heeft een keertje naar "Test" gewezen, en nu verleg je hem naar "niet test".

Tw33tst3r zei:
String type = "mountainbike";

Fiets.setType(type);

method heeft dan volgende body:
Public void setType(String type){
this.type = type;
}

Je moet weten dat type in de main method en type in de argumenten van je setType() method verschillende variabelen zijn. Op het moment dat je setType(type) aanroept, worden je actuele parameters (in dit geval type uit je main method) gekopieerd in de formele parameters (de type uit je argumenten). Je kunt zeggen dat in Java references op zich gekopieerd worden by value, terwijl de objecten zelf gekopieerd worden by reference.

De reden waarom de property van je Fiets niet verandert als je type in je main nadien verandert, is omdat het veldje type van je Fiets niet dezelfde variabele is als type in je main method. Je laat die in de main method wijzen naar een andere String, maar die in je Fiets blijft ongewijzigd.

En for the record: een String is een object, en die wrapper types (Integer, Double, ...) ook, en ze worden dus net als alle andere objecten by reference doorgegeven. De enige manier waarop ze verschillen van andere objecten is dat sommige instances gepoold/gecached worden.

Curahee Q

Legacy Member
Een string in java is ook immutable (onveranderbaar). Dit wilt dus zeggen dat wanneer je dit zou doen

Code:
String foo="";
for(int i=0; i<10; i++) {
        foo += Integer.toString(i) + " ";
}

Je bij de concatenatie telkens een nieuw object aanmaakt omdat je een string niet kan aanpassen. Met als gevolg dat wanneer je hier een oneindige lus van gaat maken je geheugen vol loopt. (Ik weet nu wel niet hoe regelmatig de garbage collector langskomt)

-----------------------------------------------------------------------
Even offtopic hoe je dit dan wel zou moeten doen
Code:
StringBuffer sb = new StringBuffer();
for(int i=0; i<10; i++) {
         sb.append(Integer.toString(i)).append(" ");       // .append() returned to stringbuffer
}

String foo = sb.toString();
-----------------------------------------------------------------------

Als je dus zegt
Code:
String foo = "Test";
String bar = foo;
Dan heb je 2 referenties die naar een geheugenplaats verwijzen met de string Test

foo ---------> Test <----------- bar

Aangezien string immutable zijn gaat hij de string waar bar naar verwijst niet aanpassen maar een nieuwe maken en de verwijzing van bar verleggen

Code:
String foo = "Test";
String bar = foo;

bar = "Nieuw String-object"
foo ---------> Test
bar ---------> Nieuw String-object

Echter wanneer je zoiets zou doen
Code:
Persoon foo = new Persoon("Jan");
Persoon bar = foo;

bar.setNaam("Jef");

Zal door de setNaam de naam zowel bij foo als bij bar veranderen in Jef.

NeverwinterX

Legacy Member
Je lijkt een beetje het effect van het aanpassen van een object via een reference te verwarren met het effect van het toekennen van een nieuwe verwijzing.

Voor de duidelijkheid stel:
Code:
public class Car {

public int number = 0;

}

Dan:

Code:
Car a = new Car();
Car b = a;
b.number = 1;
// het volgende print 1
System.out.println(b.number);
// het volgende print ook 1
System.out.println(a.number);

Dit komt omdat a en b allebei verwijzen naar hetzelfde Car object. Via b wijzig je het object waarnaar a ook verwijst.

Maar:

Code:
Car a = new Car();
a.number = 1;
Car b = a;
b = new Car();
// het volgende print 0
System.out.println(b.number);
// het volgende print 1
System.out.println(a.number);

Dit komt omdat je b naar iets anders laat verwijzen nu. Na "b = new Car();" verwijst b naar een ander object dan naar waar a verwijst.

Met String is dit niet verschillend. Het lijkt gewoon anders omdat java toelaat om:
Code:
char data[] = {'a', 'b', 'c'};
String str = new String(data);
te schrijven als:
Code:
String str = "abc";

Tw33tst3r

Legacy Member
ok thx, mensen nu snap ik het eindelijk, ik kon het wel juist toepassen (mijn vb was idd fout, maar dr leg ik de schuld van bij het late uur dak dit gepost heb :p)
wel triestig dat een "docent" bij de vdab mij dit niet kan uitleggen :s

BE|Virus

Legacy Member
Nog een eenvoudig geheugensteuntje:

In Java is elke parameter een waardeparameter. In het geval van niet primitieve variabelen/parameters is de waarde echter een referentie naar een object.
Het archief is een bevroren moment uit een vorige versie van dit forum, met andere regels en andere bazen. Deze posts weerspiegelen op geen enkele manier onze huidige ideeën, waarden of wereldbeelden en zijn op sommige plaatsen gecensureerd wegens ontoelaatbaar. Veel zijn in een andere tijdsgeest gemaakt, al dan niet ironisch - zoals in het ironische subforum Off-Topic - en zouden op dit moment niet meer gepost (mogen) worden. Toch bieden we dit archief nog graag aan als informatiedatabank en naslagwerk. Lees er hier meer over of start een gesprek met anderen.
Terug
Bovenaan