Passaggio dei parametri.


Java Sun

Earthweb
(ex Gamelan)

Jars

Java Boutique

Java Center

PIP






  JSem: 2.5

   In Java, si possono distinguere, in un primo tempo (vedremo poi che non è del tutto così) due modi per passare dei parametri ad un metodo:

  • chiamata per valori.
  • chiamata per riferimento.

  •    Chiamata per valori.

    La chiamata per valori ha luogo quando il parametro è un tipo semplice.
    Quando un parametro (di tipo semplice) è passato ad un metodo, questo può, all'interno del suo codice, modificarne il valore; tuttavia queste modifiche valgono solo all'interno del metodo. Quando il programma passa all'enunciato seguente il metodo, il parametro riprende il valore che aveva prima della chiamata del metodo.

    Esempio:

    import java.applet.*;
    import java.awt.*;
    
    public class PassParaV extends Applet{
    
    int x = 10;
    
    //metodo incremento di 1
    
    public void Inc(Graphics g, int a){
    a += 1;
    g.drawString("Valore nel metodo: " + a,5,50);
    	}
    public void paint(Graphics g){
     g.drawString("Valore prima del metodo: " + x, 5, 25);
     Inc(g,x);
     g.drawString("Valore dopo la chiamata del metodo: "+x,5,75);
       }
    }
    

    L'outpout di questa applet è:

    Valore prima del metodo: 10
    Valore nel metodo: 11
    Valore dopo la chiamata del metodo: 10
    

    La terza riga è un pò sorprendente in quanto ci si aspetterebbe che, a questo punto, il valore di x fosse 11, invece appena uscito dal metodo x ha ripreso il suo valore iniziale 10.
    Infatti, Java fa una copia del valore del parametro e mette questa copia sullo "stack" (locazione di memoria). Il metodo lavora con questa copia. Quando si esce dal metodo, Java abbandona lo stack e le modifiche apportate al parametro sono perse. Ricordiamoci che una variabile è un contenitore (locazione di memoria) che contiene dei dati (valore della variabile); al metodo viene passato il contenuto, non il contenitore. In altri termini, il metodo non conosce l'indirizzo di memoria della variabile, e quindi non può modificarne il valore.


       Chiamata per riferimento.

    La situazione è diversa quando il parametro è un oggetto, in questo caso viene effettuata una chiamata per riferimento, questo permette al metodo di accedere all'oggetto, pertanto le modifiche effettuate dal metodo saranno visibili anche fuori dal metodo.

    Esempio:

    class Intero{
    
    int x;
    
    //costruttore
    Intero(int a){
    	x = a;
    	}
    }
    

    import java.awt.*;
    import java.applet.*;
    
    public class PassParaR extends Applet{
    	Intero xI = new Intero(10);
    	
    //metodo incremento di 1 sugli oggetti della classe Intero
    
    public void IncInt(Graphics g, Intero ogg){
    	ogg.x += 1;
    	g.drawString("Valore nel metodo: "+ogg.x, 5, 50);
    	}
    
    public void paint(Graphics g){
    g.drawString("Valore prima del metodo: " + xI.x, 5, 25);
    IncInt(g, xI);
    g.drawString("Valore dopo la chiamata del metodo: "+xI.x,5,75);
       }
    }
    

    L'outpout di questa applet è:

    Valore prima del metodo: 10
    Valore nel metodo: 11
    Valore dopo la chiamata del metodo: 11
    

    Vediamo quindi che, una volta uscito dal metodo, l'oggetto conserva le modifiche apportate dal metodo.

    ATTENZIONE!! Le cose non sono poi così semplici perchè Java passa i riferimenti per valori.

    Consideriamo il problema dello scambio: per scambiare A e B si mette A in T, poi B in A e T in B. Cerchiamo di applicare questo metodo su degli oggetti, dalla discussione precedente ci sembra di avere capito come fare:

    import java.applet.*;
    import java.awt.*;
    
    public class ScambioCoppie extends Applet{
    
    Coppie X = new Coppie(0,0);
    Coppie Y = new Coppie(5,5);
    
    public void Scambio(Coppie A, Coppie B){
    A.x = 100;
    A.y = 100;
    Coppie T = A;
    A = B;
    B = T;
    }
    
    public void paint(Graphics g){
    
    g.drawString("x di X= "+X.x, 10, 15);
    g.drawString("x di Y= "+Y.x,10, 30);
    Scambio(X, Y);
    g.drawString("x di X= "+X.x, 10, 45);
    g.drawString("x di Y= "+Y.x, 10, 60);
    	}
    }
    
    class Coppie{
    
    int x,y;
    Coppie(int a,int b){
    	x = a;
    	y = b;
    	}
    }
    

    Sorprendentemente, l'output è:

    x di X = 0
    x di Y = 5
    x di X = 100
    x di Y = 5
    

    Il metodo è riuscito nel cambiare la prima coordinata di X ma lo scambio tra X e Y non è riuscito!! C'è da mettersi le mani nei cappelli!
    Per capire cos'è successo, ricordiamoci intanto che un oggetto è una serie di dati e una referenza a questi dati, nel caso specifico l'oggetto coppia X consiste nei due dati (di tipo int) prima e seconda coordinata e di una referenza a questi dati:




    quando l'oggetto viene passato al metodo, il metodo fa una copia del riferimento:





    Dopo le prime istruzioni: A.x = 100; A.y = 100; la situazione è la seguente:





    Dopo, il metodo effetua sì lo scambio, ma sulle copie dei riferimenti:


    Finalmente, quando si esce dal metodo, come al solito, le copie (dei riferimenti) vengono abbandonate e rimaniamo con:



    Ecco perchè lo scambio delle coppie può dare dei risultati inaspettati!



     next		content		previous