2014-07-04 17 views
12

So che Java è sempre passare per valore, ma non capisco il motivo per cui questo funziona:passaggio di parametri in Java

public static void swap(int[] arr, int i, int j) 
{ 
    int tmp = arr[i]; 
    arr[i] = arr[j]; 
    arr[j] = tmp; 
} 
public static void main(String[] args) 
{ 
    int[] arr = {3, 4, 5, 6}; 
    swap(arr, 1, 3); 
    // arr becomes {3, 6, 5, 4} 
} 

E questo non funziona:

public static void swap(int[] arr, int[] arr2) 
{ 
    int[] tmp = arr; 
    arr = arr2; 
    arr2 = tmp; 
} 
public static void main(String[] args) 
{ 
    int[] arr = {3, 4, 5, 6}; 
    int[] arr2 = {1, 2, 5, 6}; 
    swap(arr, arr2); 
} 

Perché?

+0

È necessario comprendere i riferimenti. –

+1

possibile duplicato di [È Java "pass-by-reference" o "pass-by-value"?] (Http://stackoverflow.com/questions/40480/is-java-pass-by-reference-or-pass -by-value) – vaxquis

+1

Java passa ** riferimenti ** per valore. –

risposta

14

Nel secondo metodo, si sta cercando di scambiare i riferimenti, che non funziona perché i riferimenti stessi sono passaggio -da-value.

Il primo metodo funziona correttamente perché modifica l'oggetto a cui fa riferimento l'array (che è mutabile), non modifica il riferimento stesso.

Verificare this blog post per ulteriori dettagli sulle differenze tra pass-by-value e pass-by-reference.

+0

Vorrei anche aggiungere che gli array sono mutabili in Java, ecco perché il primo esempio funziona. –

7

Il primo esempio è il trasferimento dei valori nell'array.

Il secondo si sta tentando di scambiare il riferimento (gli array sono oggetti in Java). I riferimenti sono copie locali (pass-by-value) e non hanno alcun effetto sul contesto di calee.

(Domanda # 56,903 su call-by-value; StackExchange dovrebbe aprire PassByValue.com ;-)

+4

passbyvalue.com già preso. – PeterMmm

+0

Suggerimento per il nome fantastico. :) Ha un pugno simile al dominio come SO ha ... – progo

3

Se avete mai usato C o C++ e sapere su come puntatori lavoro, allora ciò che ha reso questo intero scenario tick per me è la seguente dichiarazione:

In Java, everything is passed by value. 
In case of Objects, the reference (pointer) is passed by value. 

Quindi, in pratica la funzione di scambio di

public void swap(int[] a, int[] b) 
{ 
    etc. 
} 

Otterrà solo il puntatore all'array int [] a e il puntatore all'array int [] b. Stai solo scambiando due puntatori. Non è possibile modificare il contenuto di puntatori del genere.

Fondamentalmente la C equivalente è

void swap(int* a, int* b) 
{ 
    int* temp = a; 
    a = b; 
    b = temp; 
} 

int main(void) 
{ 
    int a[] = {5,6,7,8}; 
    int b[] = {1,2,3,4}; 
    swap(a,b); 
} 

Mentre anche in C, questo dovrebbe funzionare solo in questo modo:

void swap(int** a, int** b) 
{ 
    int* temp = (*a); 
    (*a) = (*b); 
    (*b) = temp; 
} 

int main(void) 
{ 
    int a[] = {5,6,7,8}; 
    int b[] = {1,2,3,4}; 
    swap(&a, &b); 
} 

Naturalmente, non è possibile inviare il riferimento di un riferimento in Java . Puntatori in questo senso non esistono in Java.

Pertanto, per modificare effettivamente l'oggetto in un'altra funzione, è necessario un oggetto "Titolare" al quale viene copiato il riferimento, ma il riferimento al suo interno all'oggetto che si desidera modificare è in realtà il riferimento effettivo di l'oggetto, se avesse senso.

E così, la seguente avrebbe funzionato:

public class ArrayHolder 
{ 
    public int[] array; 

    public ArrayHolder(int[] array) 
    { 
     this.array = array; 
    } 
} 

public void swap(ArrayHolder a, ArrayHolder b) 
{ 
    int[] temp = a.array; 
    a.array = b.array; 
    b.array = temp; 
} 

public static void main(String[] args) 
{ 
    ArrayHolder aaa = new ArrayHolder(new int[] {5,6,7,8}); 
    ArrayHolder bbb = new ArrayHolder(new int[] {1,2,3,4}); 
    swap(aaa,bbb); 
} 
1
  • Il primo swap si modificano i dati dell'array.(referenziato da arr: un riferimento) quindi viene modificato

  • Il secondo scambio, si cambia arr, arr2, due variabili locali. così quando si esce dal metodo, le due nuove variabili vengono distrutte

1
  • Arr e arr2 sono variabili locali, in modo che sarà distrutto quando la finitura metodo di swap.
  • Metodo swap esterno, le modifiche alle variabili locali non saranno interessate.
Problemi correlati