2010-10-06 5 views
5


je suis confus dans ce qui suit:
en C++ on peut passer un paramètre à une fonction de référence (ayant déclaré comme un pointeur ou d'une variable de référence) et si l'on modifie à l'intérieur du fonction, les modifications sont répercutées sur l'appelant lorsque la fonction retourne.
Cela ne se passe pas dans Java et je ne suis pas sûr de comprendre pourquoi.java vs C++ passer par référence

E.g. ceci est un procédé à partir d'un objet X

public boolean aMethod(int id, myClass aClass) 
{ 
    //do some logic 
    aClass = new MyClass(); 
    //configure argument object aClass 
    return true; 
} 

Dans le code d'appel:

//some code processing 
myClass obj = null; 
if(X.aMethod(2,obj)) 
{ 
    obj.methodA();//start using the object 
} 

Je l'utilise en C++, soit pour renvoyer un résultat qui informe que peut être utilisé le paramètre de fonction, mais en Java cela ne fonctionne pas.
J'entre la branche if (X.aMethod (2, obj)) mais l'obj est nul. Pourquoi est-ce nul?
N'ai-je pas assigné une adresse mémoire du tas en utilisant new à l'intérieur de la méthode aMethod (int id, myClass aClass)? Est-ce que je ne passe pas "l'adresse" d'obj dans la fonction? Je m'attendais à avoir l'obj correctement construit et utilisable dans le code appelant. Ai-je mal compris quelque chose concernant la mémoire dans Java?

+1

de double possible de [quelle est la différence entre passer par référence et appel par référence?] (Http://stackoverflow.com/questions/3660180/what-is-the-difference-between-pass-by-reference-and-call-by-reference) –

Répondre

26

Java passe tout en valeur - en incluant les références.

Ce que cela signifie est que si vous passez un objet, vous pouvez modifier les propriétés de cet objet, et ils persistent après votre retour, mais vous ne pouvez pas remplacer l'objet dans son intégralité avec un tout nouveau objet, car vous ne pouvez pas réellement modifier le référence - seulement ce que les points de référence.

Avant aClass = ligne:

Outside the function: 

    obj ---> <foo> 

Inside the function: 

    aClass ---> <foo> 

Après votre aClass = ligne:

Inside the function: 

    aClass ---> <bar> 

Outside the function: 

    obj ---> <foo> 

L'essentiel à noter ici est que aClass ne pointe pas obj - il pointe <foo>. Vous ne passez pas l'adresse de obj, vous passez l'adresse de ce obj points à. Ainsi, lorsque vous modifiez ce que aClass points à, cela ne touche pas obj.


Comme une autre façon de penser:

En Java,

Bar foo = new Bar(); 

est équivalent à C++,

Bar *foo = new Bar(); 

Ainsi, lorsque vous passez foo à une fonction , vous ne passez pas l'adresse de foo - vous passez l'adresse du e objet attribué. Java n'a pas la référence de passage par référence & -operator que fait C/C++.

+0

'new Bar()', vous voulez dire. :) –

+0

@Jonathan oups, faute de frappe.:) – Amber

1

Java ne peut pas faire "passer par référence".

Java utilise "passe par la valeur".

+0

Votre réponse ne fournit rien de nouveau (essentiellement répéter ce que les autres ont déjà dit en détail) et confond également/tromper les gens. Bien que Jave utilise "passer par la valeur" mais les gens peuvent encore changer les propriétés de l'objet passé. Cependant, ils ne peuvent pas réaffecter un nouvel objet entier (ce que l'OP veut faire). –

0

considèrent vos arguments de l'objet (en Java) passés en tant que tel (illustré en C++):

void method(TObject* arg); 
+0

Devrait être la méthode void (TObject * & arg); '? – Ishtar

+0

@Ishtar non,' méthode void (TObject * & arg) 'est une référence à un pointeur.arg peut être modifié (pour pointer vers une autre adresse) en interne, et sera être reflété de manière externe - de telle sorte que l'arg du client pourrait pointer vers une autre adresse quand 'method (arg)' retournera Java passe les objets comme pointeurs/par adresse Java devs aime l'appeler 'by value', mais d'un point de vue C++ est passé par pointeur (ou adresse), avec le langage qui abstrait ce fait (et les pointeurs tout à fait). ... – justin

+0

@Ishtar partie 2: en C++, passez en valeur == passez une copie de l'objet. avec Java ici, donc passer un objet Java dans la syntaxe C++ est analogue à: 'void method (TObject * arg);' – justin

3

en C++ ce qui se passerait si vous avez fait ceci:

void myFunct(int * pInt) { 
    pInt = // something; 
} 

// caller 
int x; 
int * myPointer = & x; 
myFunc(myPointer); 
// where does myPointer point now? 

l'affectation à l'intérieur myFunc aucun effet sur le pointeur de l'appelant. Maintenant, si myFunct pointeur plutôt a pris le pointeur

void myFunct(int ** ppInt) { 
    *ppInt = // something; 
} 

ou une référence au pointeur vous verriez alors un changement de l'appelant, et c'est ce que je suppose que vous avez fait.

En Java

void myFunct (Integere anInteger) { 
     // anInteger is reference to whatever is passed 
     anInteger = new Integer(99); // no effect on caller 
} 

on ne passe en effet des références à la fonction, anInteger ci-dessus est une référence à un objet appartenant à l'appelant, mais anInteger est une valeur locale à la méthode lui attribuant est la même comme assigner à un pInt dans le premier exemple, aucun effet sur l'appelant.

2

Le commentaire de votre exemple suggère que la méthode aMethod existe pour configurer l'objet. . Ainsi, au lieu de passer à zéro, que diriez-vous instanciation d'abord et passer ensuite l'objet dans Alternativement, vous pouvez faire la méthode renvoyer l'objet intead, comme ceci:

public boolean aMethod(int id) 
{ 
    myClass aClass = new MyClass(); 
    return myclass; 
} 

Et:

myClass obj = X.aMethod(2); 
if(obj != null) 
{ 
    obj.methodA();//start using the object 
} 

Alternativement, je préfère faire une convention que aMethod devrait toujours retourner un objet valide. Si ce n'est pas possible, par exemple à cause d'une erreur dans la configuration, faites en sorte que la méthode lance une exception.

Questions connexes