Catene di riferimenti - un problema inaspettato [chiuso]

0

Di seguito è riportato un codice Java con cui sto riscontrando un problema:

import java.util.HashMap;
import java.util.ArrayList;

public class MyTestClass {
  public static void main(String[] args) {
    HashMap<String, ArrayList<String>> myHashMap = new HashMap<String, ArrayList<String>>();

    ArrayList<String> catList = new ArrayList<String>();
    catList.add("Meow");

    myHashMap.put("Cat", catList);

    ArrayList<String> tempList = myHashMap.get("Cat");
    tempList.add("Purr");

    // Prints {Cat=[Meow, Purr]} as expected.
    System.out.println(myHashMap);

    ArrayList<String> copyList = new ArrayList<String>();

    copyList.add(tempList.get(0));
    copyList.add(tempList.get(1));
    // New list item
    copyList.add("Drink milk");

    tempList = copyList;
    // Prints copyList: [Meow, Purr, Drink milk]
    System.out.println("copyList: " + copyList);
    // Prints tempList: [Meow, Purr, Drink milk]
    System.out.println("tempList: " + tempList);
    // Prints {Cat=[Meow, Purr]} - why not {Cat=[Meow, Purr, Drink milk]}?
    System.out.println(myHashMap);
  }
}

Perché gli elenchi sono "passati per riferimento" (so che Java passa effettivamente tutto in base al valore, ma le liste vengono effettivamente passate per riferimento), perché tempList = copyList non rende il punto di valore HashMap a copyList?

    
posta Lord Cat 02.09.2016 - 18:43
fonte

1 risposta

3

Invece di prendere questa come richiesta off-topic per eseguire il debug del codice (vedi StackOverflow per quello), prenderò questa come una domanda su come funzionano i riferimenti java.

why doesn't tempList = copyList make the HashMap value point to copyList?

Perché la struttura dati HashMap non sa nemmeno che esiste l'identificatore tempList .

Hai una domanda simile in questo commento del codice su myHashMap :

// Prints {Cat=[Meow, Purr]} - why not {Cat=[Meow, Purr, Drink milk]}? 

Prima di tempList = copyList le cose erano così:

copyList  ---> [Meow, Purr, Drink milk]  

tempList  ---> [Meow, Purr]
                     ^
myHashMap ---> {Cat=/ }

Dopo tempList = copyList assomigliano a questo:

copyList ---,> [Meow, Purr, Drink milk]  
           /  
tempList --    [Meow, Purr]
                     ^
myHashMap ---> {Cat=/ }

Il modo in cui modifichi il valore di Cat in punti è lo stesso per crearlo in primo luogo.

Se fai questo myHashMap.put("Cat", copyList);

copyList ---,> [Meow, Purr, Drink milk]  
           /                  ^ 
tempList --    [Meow, Purr]  /
                            /
myHashMap ---> {Cat=  ------ }

Ora nulla punta a [Meow, Purr]. È stato perso ed è fuori per incontrare il suo destino con il garbage collector.

copyList, tempList e Cat non sono le strutture di dati dell'elenco. Sono cose che puntano a quelle strutture di dati dell'elenco memorizzando il loro indirizzo di memoria.

La mia casa ha un indirizzo. Se scrivi quell'indirizzo su un piccolo foglietto di carta, cammina con esso in tasca, poi estrailo, cancellalo e scrivi un nuovo indirizzo che non sposta la mia casa da nessuna parte. Invia chi riceve quel documento in un'altra casa.

Può valere la pena notare che uno dei motivi per cui questa roba è così difficile da mantenere è che tendi a cercare qualcosa che non esiste qui: identità.

[Meow, Purr] non è un'identità. Sono solo valori in una lista. tempList non è un'identità. È solo un identificatore che punta a un indirizzo. Anche un indirizzo non è un'identità. Se prendo la mia casa e la sposto nel blocco, è la stessa casa. È difficile persino parlare di queste cose quando nulla ha un'identità affidabile. Ma se ci fosse un'identità qui, sarebbe unica e immutabile. Appartenerebbe alla sola struttura dati.

    
risposta data 02.09.2016 - 19:44
fonte

Leggi altre domande sui tag