2012-04-24 14 views
5

Questo programma fornisce 6 come output, ma quando disapprovo la riga 9, l'output è 5. Perché? Penso che b.a non dovrebbe cambiare, dovrebbe rimanere 5 in main.Passaggio per valore/riferimento, che cosa?

1 class C1{ 
2  int a=5; 

3  public static void main(String args[]){ 
4   C1 b=new C1(); 
5   m1(b); 
6   System.out.println(b.a); 
7  } 

8  static void m1(C1 c){ 
9   //c=new C1(); 
10   c.a=6; 
11 } 
12 } 
+10

Java è * sempre * passa per valore, ma il valore che si sta passando è la variabile di riferimento, quindi * sembra * essere passato per riferimento in questa situazione (ma non lo è). Modifica, come afferma @mprabhat nella sua grande risposta (1+). Inoltre ho upvoted la tua domanda in quanto non vedo perché è stato downvoted. Stiamo facendo downvoting perché la gente non nasce sapendo Java? –

+1

Dovresti passare attraverso entrambe le versioni del tuo codice in un debugger e vedere la differenza. –

+1

//s.a http://stackoverflow.com/questions/40480/is-java-pass-by-reference – FailedDev

risposta

10

Quando si passa oggetto in Java sono passati come oggetto significato riferimento fa riferimento b in main metodo e c come argomento nel metodo m1, entrambi punto allo stesso oggetto, quindi quando si modifica il valore a 6 si riflette nel metodo main.

Ora, quando si tenta di fare c = new C1(); allora si fece c per puntare a un oggetto diverso ma b è ancora indicando l'oggetto cui si è creato nel metodo main quindi il valore aggiornato 6 non è visibile nel metodo principale e si ottiene 5.

+3

Ecco un buon articolo che spiega cosa sta dicendo @mprabhat con le immagini se questo ti aiuta. http://www.javaworld.com/javaworld/javaqa/2000-05/03-qa-0526-pass.html – Windle

+0

@Windle articolo molto bello +1 – mprabhat

+0

Qui dubito, 'Gli oggetti sono passati per Reference', questa dichiarazione è completamente sbagliato, IMHO in Java, invece 'Riferimenti oggetto sono passati per Valore', posso dare un esempio meraviglioso per questo, anche se i libri dicono diversamente :-) +1, anche se per il resto della parte –

3

Si passa al metodo m1 una copia di un riferimento a un oggetto di tipo C1.

Se si disapprova la linea, si sta prendendo quel riferimento e lo si punta da un'altra parte (non che il riferimento originale sta ancora puntando al primo oggetto), quindi, quando si stampa il valore di b, si stampa il valore dell'oggetto originale, che non hai cambiato.

Questa domanda ha alcune ottime risposte e dovresti davvero dargli un'occhiata.

Is Java "pass-by-reference" or "pass-by-value"?

+1

Grazie, penso ancora un po 'in termini di puntatori nella mia testa (fondamentalmente ciò che sono in sostanza), ma il riferimento è la terminologia corretta. – pcalcao

1

questo è perché c M1 (C1 c) è un riferimento a un oggetto, e quando lo fai c.a = 6 ora un IS è uguale a 6 in questo oggetto. Ma se fai c = new c1() all'interno di questo metodo, c ora fa riferimento a un oggetto completamente nuovo, quindi stai facendo c.a = 6 in questo nuovo oggetto. Dopo questo, si esce dal metodo e l'altro oggetto c ha ancora il valore 5

1

Il metodo viene chiamato in main, causando una nuova istanza creata in m1 per sostituire l'istanza di C1 già creata nel metodo main. Se si commenta l'istanza in m1, la prima istanza in main ha quindi effetto. Questo perché negli oggetti java vengono passati per riferimento non per valore.

3

Java è un valore pass-by-value, in parole povere che significa che quando si passa un argomento si crea una copia della variabile del puntatore . Le variabili oggetto dovrebbero essere realmente lette come puntatori in C: questo rende le cose più facili da capire, almeno quando provengono dal mondo C (dove C è solo un valore pass-by).

Così quando si fa c=new C1(), o in generale durante l'esecuzione di qualsiasi incarico a c, si stanno facendo c (che in passato ha sottolineato la stessa posizione di memoria che b appuntita) il punto in un'altra posizione. Quindi il seguente c.a=6 è un'assegnazione a un membro dell'oggetto indicato da c, che non è più l'oggetto puntato da b.

1

In Java diverso dai tipi primitivi tutto viene passato per riferimento, anche se dice passare la copia del riferimento.

Quindi nel vostro caso in primo luogo entrambi i puntatori b e c puntano allo stesso oggetto, quindi il valore aggiornato viene riflesso nel metodo principale.

In seconda istanza quando si effettua il c per puntare a un nuovo oggetto (chiamando new) b sta ancora puntando all'oggetto creato nel metodo main, quindi il valore aggiornato non si riflette nel metodo main poichè b e c puntano a due oggetti diversi.