Variabili modificate all'interno del metodo, come fare per lasciarle intatte?

di il
3 risposte

Variabili modificate all'interno del metodo, come fare per lasciarle intatte?

Salve a tutti,
Premessa, sono un principiante per quanto riguarda JAVA. Ho una domanda da fare a voi del forum.
Come esercizio di prova ho creato un semplice programma che ti chiede di inserire in un array 10 valori int, poi li riordina all'interno di un metodo.
Ecco il codice, che funziona, ovvero riordina l'array iniziale:

/*
* Inserire 10 valori in un array in ordine casuale
* Poi ordinare l'array
*/
import java.util.Scanner;       //Importo il modulo per inserire dei dati tramite terminale, senza questo non puoi inserire i numeri                                     
    public class OrdinamentoArray {  //Dichiaro la class OrdinamentoArray, stesso nome del nome file
        public static void main(String[] args){         //main void metodo principale
            int array[] = new int[10];                  //creo la variabile chiamta "array" ovvero un array di [n] elementi (n=3) 
            int array_ordinato[] = new int[10];
            int i = 0;                                  //dichiaro variabile "i" per i contatori
            Scanner console = new Scanner(System.in);   //serve per l'immisione dei dati, vedi import, prima istruzione
            while(i < array.length){                                                                               //ciclo while iniziale 
                System.out.print(" Inserire il valore per l'elemento " + (i+1) + "/"+ array.length + " dell'array: ");  //comunico al terminale che voglio un numero
                array[i] = console.nextInt();                                                                           //il dato in ingresso lo memorizzo all nella posizione [i] dell'array         
                i++;                                                                                                    //incremento i per il ciclo while
            }
            i = 0;  //resetto il contatore "i"
            while(i < array.length){                                                                       //secondo while, ri-comunico l'array
                System.out.println(" L'elemento numero " + (i+1) +" dell'array ora è:" + array[i]);
                i++;
            }   
            i=0;
            array_ordinato = Ordina_min_max(array);  //assegno all'array_ordinato i risultati che tornano dal metodo Ordina_min_max. Così è utile.
            while(i < array.length){                                                                       //ri-comunico il contenuto dell'array
                System.out.println(" L'elemento numero " + (i+1) +" dell'array iniziale era:" + array[i]);
                i++;
            }
            i=0;
            while(i < array_ordinato.length){                                                                       //ri-comunico il contenuto dell'array
                System.out.println(" L'elemento numero " + (i+1) +" dell'array ordinato ora è:" + array_ordinato[i]);
                i++;
            }
            System.out.println("FATTO! inserie un qualsiasi valore e premere invio per uscire.");   // messaggio di servizio
            int exit_char = console.nextInt();  
        }
        private static int[] Ordina_min_max (int[] array_metodo){//programmo il metodo "Ordina_min_max" importando in "array_non_ordinato" 
            //<modif> <tipo>  <nome>        (<par formali>)    {<corpo>} 
            //<modif>: Modificatori. Descrivono proprietà del metodo come visibilità (da chi può essere usato), modificabilità, appartenenza ad una classe o alle istanze.
            //<tipo>: Il tipo del metodo. E' il tipo del valore restituito dal metodo, oppure void.
            //<nome>: Il nome del metodo. E' un identificatore qualunque, che individua il metodo all'interno della classe.
            //<par formali>: I parametri formali. Una lista (anche vuota) di coppie <tipo> <parametro> separate da virgole, dove <tipo> è un tipo di dato e <parametro> è una variabile (identificatore)
            //<corpo>: Il corpo del metodo. Un blocco che contiene istruzioni fra cui una o più istruzioni return
            //il contenuto di "array" del metodo "main"tramite metodo selction sort 
            int i = 0;                          //reset contatore
            int j = 0;
            int minValIndex = 0;
            System.out.println("Riordino l'array iniziale.");           //Comunico all'utente
            for (i = 0; i<array_metodo.length; i++){                    //scansiono l'array n volte (n=grandezza array) partendo ogni volta dall'indice successivo 
                for (j=i; j<array_metodo.length; j++){                  //ad ogni scansione salvo l'inice del valore minore trovato nella variabile minValIndex
                    if (array_metodo[j] < array_metodo[minValIndex]){   
                        minValIndex = j;
                        int val = array_metodo[j];
                    }
                }
                int temp = array_metodo[i];                             //qui scambio il valore minimo trovato con il valore in posizione [i]
                array_metodo[i]=array_metodo[minValIndex];              //ad ogni scansione dell'array il numero minore viene messo incima alla lista
                array_metodo[minValIndex]=temp;
                minValIndex = i+1;      //re-inizializzo minvalindex per farlo tornare alla posizione inizale
                                        //altriemetni non cerca tutto l'array
            }
             return array_metodo;
        }
}
Funzionamento:
-Chiedo all'utente di inserire i 10 valori e li salvo nella variabile chiamata "array";
-Riordino tramite il metodo "Ordina_min_max" e salvo il risultato dentro a "array_ordinato";
-Stampo il contenuto dei due array: l'iniziale "array" e il finale "array ordinato".

Il problema è che, alla fine, quando vado a stampare il contenuto di "array", l'array iniziale, me lo trovo ordinato pure lui.
Quindi all'interno del metodo, modifica la variabile "array". Io non voglio che succeda.

Perché all'interno del metodo modifico anche la variabile "array"?
Come faccio per far si che non succeda? a parte il crearsi una copia locale all'interno del metodo (o forse quello è l'unico metodo).


Grazie in anticipo,
Daniele

3 Risposte

  • Re: Variabili modificate all'interno del metodo, come fare per lasciarle intatte?

    danz892 ha scritto:


    Perché all'interno del metodo modifico anche la variabile "array"?
    Perché al metodo Ordina_min_max viene passata una copia del riferimento all'array, quindi il metodo "vede" lo STESSO oggetto array che ha il main.

    danz892 ha scritto:


    Come faccio per far si che non succeda? a parte il crearsi una copia locale all'interno del metodo (o forse quello è l'unico metodo).
    Basta creare una copia ("clone") dell'array e operare l'ordinamento sulla copia. Dove farlo, se nel main o nel Ordina_min_max, è valutabile.

    Per "clonare" un array ci sono diversi modi ma parlando di un int[] una soluzione banale è usare il clone() degli oggetti:
    int[] arrClonato = arrOriginale.clone();
    A partire da Java 5 non c'è neanche bisogno del cast, perché il clone() degli array sfrutta il tipo di ritorno "covariante" (il clone() di un int[] restituisce un int[] ... non più solamente Object come pre Java 5).


    P.S. invece di fare
                i = 0;
                while(i < array.length){
    
                    i++;
                }   
    Usa un classico ciclo "for".
  • Re: Variabili modificate all'interno del metodo, come fare per lasciarle intatte?

    Grazie mille della risposta.
    Quindi in futuro devo stare attento a quello che passo dentro al metodo. Se non voglio che venga modificato, crearmi la copia.
    Ma non esiste proprio un modo per "bloccare" la modifica di una variabile?
    Scusa non so come spiegarlo meglio
  • Re: Variabili modificate all'interno del metodo, come fare per lasciarle intatte?

    danz892 ha scritto:


    Ma non esiste proprio un modo per "bloccare" la modifica di una variabile?
    Il problema non sono le variabili ma la "mutabilità" degli oggetti.

    Prendi questo stringatissimo esempio scritto al volo:
    public class Esempio {
        public static void main(String[] args) {
            Persona p1 = new Persona();
            p1.setNome("Mario");
    
            System.out.println(p1.getNome());   // stampa: Mario
    
            prova(p1);
    
            System.out.println(p1.getNome());   // stampa: Roberto
        }
    
        public static void prova(Persona pers) {
            pers.setNome("Roberto");
        }
    }
    
    class Persona {
        private String nome;
    
        public String getNome() {
            return nome;
        }
    
        public void setNome(String nome) {
            this.nome = nome;
        }
    }
    Quando prova() viene invocato, riceve in argomento una copia dello stesso valore contenuto in p1, che è un riferimento ad un oggetto. Ma attenzione, sono variabili differenti, una è p1 (del main), l'altra è pers (parametro di prova). Quindi sia prova() che main() hanno il riferimento allo STESSO identico oggetto.

    Ma l'oggetto è "mutabile" perché ha un setNome(), quindi prova() PUÒ modificare lo "stato" dell'oggetto.

    Quello che prova() NON può assolutamente fare è cambiare il valore che ha p1 nel main() (es. assegnargli un altro oggetto Persona), perché prova non ha alcuna visibilità/accesso alle variabili locali di altri metodi.

    Quindi o si fa una copia "difensiva" dell'oggetto oppure si usano oggetti "immutabili" (come funzionano Integer, Long, String e molte altre classi).

    E gli elementi di un array sono sempre, purtroppo, mutabili (non è possibile diversamente) e quindi puoi sempre cambiarne il valore.
Devi accedere o registrarti per scrivere nel forum
3 risposte