2015-09-11 15 views
5

Supporti Java passano per valore (funziona sempre su una copia) ma quando si passa un oggetto definito dall'utente, esso cambia l'oggetto reale (tipo di passaggio per riferimento ma nessun puntatore cambia), che I capisci, ma perché il metodo changeObject2CLEAR di seguito sta effettivamente cambiando il valore dell'oggetto? Invece deve lavorare sulla copia?Problema con valore in java


import java.util.HashMap; 
import java.util.Map; 

public class PassBy { 

    class CustomBean { 
     public CustomBean() { 

     } 

     private int id; 
     private String name; 

     public int getId() { 
      return id; 
     } 
     public void setId(int id) { 
      this.id = id; 
     } 
     public String getName() { 
      return name; 
     } 
     public void setName(String name) { 
      this.name = name; 
     } 

     @Override 
     public String toString() { 
      return id + ", " + name; 
     } 
    } 

    public Map<Integer, String> changeObject2NULL (Map<Integer, String> m) { 
     m = null; 
     return m; 
    } 

    public Map<Integer, String> changeObject2CLEAR (Map<Integer, String> m) { 
     m.clear(); 
     return m; 
    } 

    public CustomBean changeCustomObject (CustomBean _e) { 

     _e.setId(_e.getId() + 1); 
     return _e; 
    } 

    public static void main(String[] args) { 

    PassBy passby = new PassBy(); 

    Map<Integer, String> map = new HashMap<Integer, String>(); 
    map.put(1, "value"); 

    CustomBean bean = passby.new CustomBean(); 
    bean.setId(1); 
    bean.setName("arun"); 

    // Initial Value 
    System.out.println(map.toString()); 
    System.out.println(bean.toString()); 
    System.out.println("-------------------------"); 

    // Pass by value works fine 
    passby.changeObject2NULL(map); 
    passby.changeCustomObject(bean); 

    // Custom object value changes since we pass as the object reference but Map remains with actual value 
    System.out.println(map.toString()); 
    System.out.println(bean.toString()); 
    System.out.println("-------------------------"); 

    // Testing Pass by value - CANT UNDERSTAND why it changed the object since it has to be pass-by-value and not by ref in this case ?? 
    // Why setting to null not chainging the value but clear does ? 
    passby.changeObject2CLEAR(map); 
    System.out.println(map.toString()); 

    } 
} 
+0

Stai passando il * riferimento * in base al valore. Un sacco su questo su Google. Buona domanda però. – Bathsheba

+1

@Arun Ho aggiornato la mia risposta per indirizzare la forma raffinata della tua domanda –

+0

In breve 'changeObject2NULL (Map m)' contiene la propria variabile * local * 'm', che è anche il parametro del metodo. Quando si utilizza questo metodo come 'changeObject2NULL (map)' 'm' copia le informazioni su quale oggetto' map' tiene (questo indirizzo è * valore * della variabile 'map'). Quindi quando chiamate 'm.clear()' invoca il metodo 'clear' sullo stesso oggetto che' map' tiene in modo da poter vedere il nuovo stato di quell'oggetto tramite 'map'.Quando si chiama 'm = null' si cambia semplicemente quale oggetto' m' vale per 'null'; questo non influenza 'map' né l'oggetto a cui si riferisce. – Pshemo

risposta

1

Quando si chiama changeObject2CLEAR

passby.changeObject2CLEAR(map); 

si sta passando l'istanza map.

nel metodo changeObject2CLEAR

public Map<Integer, String> changeObject2CLEAR (Map<Integer, String> m) { 
    m.clear(); 
    return m; 
} 

si eseguono .clear() su quella stessa istanza map anche se nel metodo si chiama m.

Come esercizio per capire che il seguente metodo farà la stessa cosa.

public void changeObject2CLEAR (Map<Integer, String> m) { 
    m.clear(); 
} 

Si noti che non c'è bisogno di restituire l'Map<Integer, String> m perché il map si ha accesso è lo stesso oggetto istanza passato nel laddove il metodo viene chiamato.

MODIFICA: perché m = null; si comporta come un valore pass-by ma come m.clear() si comporta come passaggio per riferimento?

Quando 'assegnare' il valore di nullm si cambia il riferimento dalla precedente oggetto istanza map in una nuova posizione di memoria che è null.

Quando si richiama il metodo .clear() sull'oggetto esempio m si chiama il metodo sullo stesso oggetto che si trova nella posizione di memoria fa riferimento map, quindi si modifica l'oggetto map.

0

per quanto ne so Java fa solo passaggi per valore, ma i valori sono in realtà fa riferimento

+0

Questo vale per le istanze 'Object' ma non per i tipi primitivi –

+0

Perché l'impostazione su null è pass-by-value ma il metodo clear è pass-by-ref? – AKS

+0

'null' è un riferimento, quindi assegnando null, stai cambiando il riferimento nell'attuale scope, quindi" perdendo "l'oggetto su cui stavi lavorando, mentre cancella l'oggetto il cui riferimento hai passato nella funzione – miau

3

Così mi permetta di provare che aiuta a capire, Java non sempre passa per valore, ma sono sicuro di sapere che tutte le istanze dell'oggetto sono in realtà dei puntatori a quegli oggetti. Ora quando si invia un oggetto, si passa un valore dell'indirizzo dell'oggetto. Se si apportano modifiche all'oggetto stesso (come m.clear()), allora si passa a quell'indirizzo, si digita l'oggetto e si esegue l'operazione su di esso. Ma se cambi il puntatore stesso, come m = null, allora cambia solo la copia dell'indirizzo che stai tenendo.

+2

downvoter, cura di commentare? Questa è la risposta corretta. Almeno, non una risposta sbagliata. –

+0

Poiché la domanda è duplice, sto votando su tutte le risposte sia in questa domanda che nel duplicato. Le risposte nel duplicato sono di gran lunga superiori a questo. Quindi, IMO, non aggiunge nulla di utile. Se hai qualcosa da aggiungere, quindi aggiungi la risposta al duplicato. – Bathsheba

+1

@Bathsheba Mentre sei naturalmente libero di downvotare a tuo piacimento, trovo che una buona regola empirica sia quella di downvotare quando una domanda è attivamente sbagliata o dannosa. Se non è buono come un'altra risposta, allora inviterò la risposta migliore e lascerò intatta la risposta meno buona. In altre parole, aiuto le risposte migliori a salire in alto, e non mi preoccupo di cercare di far affondare le risposte meno buone. – yshavit