Black Friday = Pricewatch Bekijk onze selectie van de beste Black Friday-deals en voorkom een miskoop.

[Java] object vervangen

Pagina: 1
Acties:

  • Rene59
  • Registratie: April 2000
  • Laatst online: 08-11 18:52
Beetje lastig uitleggen, hopelijk is het te begrijpen:

Ik vroeg mij af of het mogelijk is om een object te vervangen door een nieuw object van een ander (subklasse) type.
Ter illustratie, dit stukje code:
code:
1
2
3
4
5
6
public void foo(Dog d) {
  d = new Dog("Fifi");
}

Dog aDog = new Dog("Max");
foo(aDog);

Nu weet ik dat wat hierboven staat niet het beoogde doel zal bereiken; aDog blijft ongewijzigd en dus "Max" heten.
Is er een manier om dit wél voor elkaar te krijgen binnen de foo method?
En als dat kan, dan nog een stapje verder: is het ook mogelijk om het object te vervangen door een subklasse van Dog?

  • Herko_ter_Horst
  • Registratie: November 2002
  • Niet online
Nee, het is niet mogelijk een referentie naar een object te veranderen op deze manier omdat referenties in Java by-value worden doorgegeven. Maar waarom denk je dit te willen? Wat is het doel?

Het is uiteraard wél mogelijk een (referentie naar een) nieuw object te retourneren uit die methode en die toe te kennen aan de oorspronkelijk variabele:
Java:
1
2
3
4
5
6
public Dog foo(Dog d) {
 return new Dog("Fifi");
}

Dog aDog = new Dog("Max");
aDog = foo(aDog);
De waarde die je retourneert mag uiteraard ook een subclass van Dog zijn.

[ Voor 47% gewijzigd door Herko_ter_Horst op 03-07-2008 17:08 ]

"Any sufficiently advanced technology is indistinguishable from magic."


  • NetForce1
  • Registratie: November 2001
  • Laatst online: 17-11 20:32

NetForce1

(inspiratie == 0) -> true

Dat gaat niet werken, een toekenning in Java kopieert de refentie van het object naar de variabele. Je krijgt dan dus precies het gedrag wat jij beschrijft (en zoals het ook in vele java tutorials / boeken staat).
Wat je kan doen in dit geval is een wrapper object gebruiken, zoiets:
Java:
1
2
3
4
5
6
7
8
9
10
11
class DogHolder {
    Dog dog;
}
public void foo(DogHolder h) {
  h.dog = new Dog("Fifi");
}

Dog aDog = new Dog("Max");
DogHolder holder = new DogHolder();
holder.dog = aDog;
foo(holder);

De wereld ligt aan je voeten. Je moet alleen diep genoeg willen bukken...
"Wie geen fouten maakt maakt meestal niets!"


  • Rene59
  • Registratie: April 2000
  • Laatst online: 08-11 18:52
Bedankt voor de reacties. Da's dus waar ik al bang voor was.
Reden dat ik het me afvroeg is omdat ik met een applicatie zit waarvan ik de implementaties van klassen niet mag wijzigen. Ik ben genoodzaakt van alles wat ik wil wijzigen een subklasse te maken, die eventueel weer registreren in configuratie xml's, verwijzingen in andere klassen weer aanpassen die dan ook weer een subklasse moeten worden etc. Steeds een hoop gepiel voor een kleine wijziging.

  • redfox314
  • Registratie: December 2004
  • Laatst online: 07-11 14:35
eventueel kan je met eigen DTO's (Data Transmission Objects) werken. . Je schrijft dus eigenlijk een soort wrapper rond Dog. (gewoonlijk om rond protected default constructors te geraken). bvb.

Java:
1
2
3
4
5
6
7
class DogDTO{
private Dog d;

public Dog getDog(){
return d;
}
}

op deze manier kan je alle manipulaties op dog uitvoeren met een object waarvan jij de regels bepaald.

***Edit*** NetForce suggereert eigenlijk hetzelfde maar benoemt het met een generiekere term

[ Voor 77% gewijzigd door redfox314 op 03-07-2008 23:04 ]


  • creator1988
  • Registratie: Januari 2007
  • Laatst online: 17-11 14:03
In c# heb je een ref, dus iets als public void foo (ref Dog a)

Bestaat zoiets niet in java?

  • RayNbow
  • Registratie: Maart 2003
  • Laatst online: 10:46

RayNbow

Kirika <3

creator1988 schreef op vrijdag 04 juli 2008 @ 08:58:
In c# heb je een ref, dus iets als public void foo (ref Dog a)

Bestaat zoiets niet in java?
Zie:
Herko_ter_Horst schreef op donderdag 03 juli 2008 @ 17:03:
Nee, het is niet mogelijk een referentie naar een object te veranderen op deze manier omdat referenties in Java by-value worden doorgegeven.
Alles in Java is Pass By Value.

Ipsa Scientia Potestas Est
NNID: ShinNoNoir


  • redfox314
  • Registratie: December 2004
  • Laatst online: 07-11 14:35
In java is alles call by reference!!!

Dus als je in een functie foo
d.setName("fifi") zou doen dan zou je dat in aDog zien.
MAAR
de assignment operator verandert waar d naar wijst maar niet waar aDog naar wijst.
Je moet d en aDog zien als je adreskaartje. De oproep van foo(aDog) is alsof je iemand een adreskaartje geeft. De uitdrukking d=new Dog(...); is alsof iemand op een van je uitgedeelde adreskaartjes jou adres doorstreept en vervangt door een ander. Dat heeft niet direct invloed op alle andere uitgedeelde adreskaartjes. (Hou zou wel grappig zijn dat het vervangen van een adres op een adreskaartje jou onmiddellijke verhuis zou bewerkstelligen). Het is echter wel call by reference want als er niemand aan jou adreskaartje knoeit komt iedereen bij je huis uit.

Verwijderd

redfox314 schreef op maandag 07 juli 2008 @ 21:43:
In java is alles call by reference!!!
Definieer reference... :)

  • Kwistnix
  • Registratie: Juni 2001
  • Laatst online: 07:37

  • redfox314
  • Registratie: December 2004
  • Laatst online: 07-11 14:35
een reference is een object dat omschrijft waar bepaalde gegevens te vinden zijn.

In principe zou je wel kunnen zeggen dat java een pass by value doet. Het kopieert namelijk de reference van een object naar de functie (zoals Herko_ter_Horst al zei). Dat geeft echter wel het effect van een pass by reference van het object.

Primitieve types worden echter wel by value doorgegeven.

Meer in detail heb je in java twee soorten types. Reference types en primitive types.
deze worden by-value doorgegeven.
Dat kan je echter wegabstraheren en dan krijg je de voorgaande uitleg.

  • Remus
  • Registratie: Juli 2000
  • Laatst online: 15-08-2021
redfox314 schreef op maandag 07 juli 2008 @ 23:11:
een reference is een object dat omschrijft waar bepaalde gegevens te vinden zijn.

In principe zou je wel kunnen zeggen dat java een pass by value doet. Het kopieert namelijk de reference van een object naar de functie (zoals Herko_ter_Horst al zei). Dat geeft echter wel het effect van een pass by reference van het object.

Primitieve types worden echter wel by value doorgegeven.

Meer in detail heb je in java twee soorten types. Reference types en primitive types.
deze worden by-value doorgegeven.
Dat kan je echter wegabstraheren en dan krijg je de voorgaande uitleg.
Het probleem met jouw beschrijving dat in de informatica 'pass by reference' een specifieke betekenis heeft die jij hier negeert. Pass by reference betekent namelijk dat de functie het geheugenadres met daarin de verwijzing naar het object doorgeeft.
Wijzigingen in dat geheugenblok hebben dus ook invloed op alle anderen objecten ed die dat geheugenadres gebruiken voor de verwijzing naar het object. In java wordt slechts een kopie van de verwijzing (dus de referentie op dat geheugenadres, niet een kopie van het object!) teruggegeven. Toekenning van een nieuwe referentie heeft dus slechts lokaal effect.

Dat is dus 'pass by value', je moet daarbij in het oog houden dat daarbij de value een verwijzing is naar een object en niet het object zelf (of zoals ik het ooit ergens heb zien noemen 'pass by reference-value')

  • Herko_ter_Horst
  • Registratie: November 2002
  • Niet online
Een van de belangrijkste karakteristieken van "pass-by-reference" is dat je binnen een method de waarde van een parameter kunt veranderen zodat dat buiten de method zichtbaar is. Dat kan niet in Java.
Java:
1
2
3
4
5
6
7
String aString = "aap";
notCalledByReference(aString);
System.out.println(aString); // hier staat altijd aap, niet noot

public void notCalledByReference(String someString) {
  someString = "noot"; // deze regel verandert de value van someString, dit is echter een kopie van de waarde van aString en is niet zichtbaar buiten deze method
}

Wat natuurlijk wél kan (en wat vaak onterecht als tegenargument wordt gebruikt) is dat je via een reference de interne staat van het object waar de reference naar wijst kan veranderen.
Java:
1
2
3
4
5
6
7
8
StringBuilder aStringBuilder = new StringBuilder("aap");
notCalledByReference(aStringBuilder);
System.out.println(aStringBuilder); // nu komt er wél noot te staan

public void notCalledByReference(StringBuilder someStringBuilder);
  someStringBuilder.clear();
  someStringBuilder.append("noot");
}


De verwarring zit hem in het feit dat het woord "reference" in "pass-by-reference" iets anders betekent dan een "reference" (naar een object) in Java.

Met pass-by-reference krijg je een referentie (pointer) naar de oorspronkelijke variabele, in pass-by-value krijg je (een kopie van) de waarde van de oorspronkelijke variabele. Dit heeft dus niets te maken met references naar objecten (zoals in Java), maar met references naar variabelen (wat in Java niet bestaat).

In Java krijg je dus het laatste: in het geval van primitive values krijg je de waarde van die primitive, in het geval van reference values krijg je de waarde van die reference.

"Any sufficiently advanced technology is indistinguishable from magic."


  • redfox314
  • Registratie: December 2004
  • Laatst online: 07-11 14:35
Ik vind de specifieke betekenis die jij hier aanhaalt niet op zo'n eenduidige manier terug. Bovendien is heel het gegeven van geheugen adres een implementatiedetail. De meest universele definitie van het verschil pass by reference/value die ik ben tegengekomen luidt als volgt:
Bij pass by value krijgt een functie een kopie van het argument mee terwijl bij pass by reference krijgt een functie een referentie naar het argument mee.
Het doet er dus niet toe of die referentie gekopieerd is of niet. Een zogenaamde echte pass by reference zou dan een reference naar een reference geven.

  • Herko_ter_Horst
  • Registratie: November 2002
  • Niet online
De meest universele definitie van het verschil pass by reference/value die ik ben tegengekomen luidt als volgt:
Bij pass by value krijgt een functie een kopie van het argument mee terwijl bij pass by reference krijgt een functie een referentie naar het argument mee.
Hoe wijkt dit af van wat ik zei? "Met pass-by-reference krijg je een referentie (pointer) naar de oorspronkelijke variabele, in pass-by-value krijg je (een kopie van) de waarde van de oorspronkelijke variabele."

Nog even voor de volledigheid de link naar Wikipedia: Evaluation strategy
Een zogenaamde echte pass by reference zou dan een reference naar een reference geven.
Precies, en dat is wat in Java dus NIET gebeurd.

Het komt er in elk geval op neer dat Java pass-by-value gebruikt, waardoor wat de TS wil niet mogelijk is.

[ Voor 10% gewijzigd door Herko_ter_Horst op 08-07-2008 14:58 ]

"Any sufficiently advanced technology is indistinguishable from magic."


  • Remus
  • Registratie: Juli 2000
  • Laatst online: 15-08-2021
redfox314 schreef op dinsdag 08 juli 2008 @ 13:50:
Ik vind de specifieke betekenis die jij hier aanhaalt niet op zo'n eenduidige manier terug. Bovendien is heel het gegeven van geheugen adres een implementatiedetail. De meest universele definitie van het verschil pass by reference/value die ik ben tegengekomen luidt als volgt:
Bij pass by value krijgt een functie een kopie van het argument mee terwijl bij pass by reference krijgt een functie een referentie naar het argument mee.
Het doet er dus niet toe of die referentie gekopieerd is of niet. Een zogenaamde echte pass by reference zou dan een reference naar een reference geven.
Ik maakte gebruik van de term geheugenadres om de ambiguiteit van het woord referentie of reference te vermijden. Het probleem is namelijk dat in veel tekstboeken het woord reference wordt gebruikt voor een verwijzing naar de variabele zelf (zij het een primitief type, een verwijzing naar een object etc), terwijl in Java in de context van objecten het begrip reference wordt gebruikt voor de inhoud van de variabele (een verwijzing naar het object).

In talen met pass-by-reference wordt de reference naar de variabele overgedragen (een beetje simpel geformuleerd: de parameternaam in de methode wordt een alias voor een reeds bestaande variabele), in pass-by-value wordt de inhoud van de variabele gekopieerd (de parameternaam in de methode wordt een nieuwe variabele).

Verder denk ik dat hierboven verder wel duidelijk beschreven is wat het verschil in werking is.
Pagina: 1