Variabili e procedure

A prima vista, può sembrare che le procedure siano semplicemente un modo per raccogliere insieme una sequenza di istruzioni, in modo da avere un nome per questa sequenza. Le cose non stanno esattamente cosí. La principale differenza è che all'interno di una procedura non si possono usare le variabili che sono dichiarate all'interno del programma principale. In altre parole, il seguente programma non viene compilato:

class Zero {
  static annulla() {
    a=0;
  }

  public static void main(String[] args) {
    int a;

    anulla();
    System.out.println(a);
  }
}
A prima vista, potrebbe sembrare che scrivere a=0 nel programma oppure annulla() sia esattamente la stessa cosa. Il problema è che le variabili del programma non possono venire usate in nessun modo nelle istruzioni all'interno della procedura.

D'altra parte, è possibile dichiarare ed usare delle variabili all'interno della procedura. Queste variabili non saranno però visibili al programma principale, ossia non potranno venire usate dalle istruzioni del programma principale. Queste variabili sono dette variabili locali della procedura.

Supponiamo per esempio di voler realizzare una procedura che stampa venti linee bianche. Possiamo ripetere la stampa di una linea bianca per venti volte, usando un ciclo for. Per poter usare il ciclo for occorre una variabile di tipo intero che vada da 1 a 20. Non possiamo dichiarare questa variabile nel programma principale (cioè dopo il public static void main...) perché in questo modo la procedura non potrebbe usarla. È quindi necessario dichiarare questa variabile all'interno della procedura, nel modo seguente:

class LineeBianche {
  static void diecilinee() {
    int i;

    for(i=1; i<=20; i=i+1) {
      System.out.println(" ");
    }
  }

  public static void main(String[] args) {
    ....

    diecilinee();

    ...

  }
}
È possibile avere più procedure, oltre al programma principale. In oguna di queste procedure si possono definire delle variabili. La regola in questo caso è

le variabili definite all'interno di una procedura si possono usare solo dentro la procedura stessa
Prendiamo in considerazione il seguente programma StessoNome.java:

/*
  Due variabili con lo stesso nome: una nella procedura
  e una nel programma.
*/

class StessoNome {
  static void esempio() {
    int a;

    a=12;
  }

  public static void main(String[] args) {
    int a;

    a=90;

    esempio();

    System.out.println(a);
  }
}

Si analizzi il programma e si provi a capire che cosa viene stampato. A prima vista può sembrare che si stampa il valore 12: infatti, la variabile a viene assegnata a 90, poi si chiama la procedura che ci mette il valore 12, e poi si stampa il contenuto. In realtà, il programma stampa il numero 90.

Per capire il perchè, occorre capire come viene organizzata la memoria. La situazione che si viene a creare nella memoria è la seguente:

esempio
a
    
      
 
 
main
a
    
      
 

A parole: la procedura esempio ha una sua zona di memoria, che è un contenitore in cui vengono messe le variabili locali alla procedura. La variabile a dichiarata all'intero di esempio è una casella all'interno di questo contenitore.

D'altra parte, il programma principale (main) ha una sua zona di memoria, che è il contenitore in cui vengono create le sue variabili Quindi, la variabile a dichiarata all'interno di main è una casella all'interno di questa zona.

È quindi chiaro che la due variabili, anche se hanno lo stesso nome, corrispondono a due zone di memoria diverse. È quindi possibile che il contenuto sia diverso; più precisamente, mettendo un valore in una delle due variabili, l'altra rimane inalterata.

Vediamo ora come viene creata questa situazione, ossia eseguiamo il programma passo per passo. Inizialmente, la memoria è vuota.

esempio
 
    
      
 
 
main
 
    
      
 

Per prima cosa viene creata la variabile a del programma:

esempio
 
    
      
 
 
main
a
    
      
 

In questa variabile viene messo il valore 90:

esempio
 
    
      
 
 
main
a
  90
      
 

A questo punto si chiama la procedura esempio. Questa procedura crea una sua variabile locale (nel suo contenitore/zona di memoria) che ha ancora nome a. Quindi la situazione che si ha a questo punto è la seguente:

esempio
a
    
      
 
 
main
a
  90
      
 

La procedura esempio contiene una istruzione a=12. Questo significa: metti il valore 12 nella variabile a. Abbiamo però due variabili a in questo momento. Dal momento che questa istruzione si trova nella procedura esempio, la variabile a è quella della zona di memoria di memoria di esempio, che nel grafico è il contenitore di sopra. Quindi a=12 mette il valore 12 nella variabile a locale della procedura esempio:

esempio
a
  12
      
 
 
main
a
  90
      
 

A questo punto la procedura termina e si ritorna ad eseguire il programma principale dal punto in cui lo si era lasciato. In questo caso, l'istruzione subito dopo la chiamata di procedura è System.out.println(a), che stampa il valore della variabile a. Anche in questo caso abbiamo il dubbio di quale sia la variabile a, se quella del programma o quella della procedura esempio. Dal momento che la istruzione di stampa si trova all'interno del programma, la variabile da usare è quella del programma, ossia quella che attualmente contiene il valore 90. Il risultato dell'esecuzione di questo programma è quindi la stampa del numero 90.