Variabili globali

Il meccanismo con cui le procedure interagiscono con il programma principale visto fino ad ora è quello del passaggio dei parametri (con cui il programma manda dei dati alle procedure) e il valore di ritorno (return, con cui la funzioni mandano dati al programma principale quando hanno terminato).

Esiste un altro meccanismo che permette al programma e alle procedure di comunicare, ed è quello delle variabili globali.

Come si è visto fino ad ora, le variabili dichiarate all'interno di una procedura e le variabili dichiarate nel programma principale sono diverse, e ogni blocco può accedere alle sole variabili dichiarate all'interno del blocco stesso. Per esempio, nel seguente programma java la variabile x dichiarata nella procedura test è diversa dalla variabile x del programma principale, anche se il nome è lo stesso.

class Prova {
  static void test() {
    int x;

    ...
  }

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

    ...
  }
}
Infatti, la situazione che si viene a creare nella memoria è la seguente:

test
x
    
      
 
 
main
x
    
      
 
Se per esempio si mette x=10 dentro il main, la variabile in cui viene messo il 10 è la variabile che sta nel contenitore di main. Se si esegue System.out.println(x) dentro il main, viene stampato il contenuto della casella x che sta dentro il contenitore di main, ecc. Lo stesso vale per l'altra variabile x, cioè quella del contenitore della procedura test: solo le istruzioni che stanno dentro test possono modificare il contenuto di questa variabile, e solo queste possono accedere al contenuto precedentemente memorizzato. Si può dire che le due variabili, anche se hanno lo stesso nome, sono due variabili diverse.

Le variabili globali sono variabili che possono venire usate da tutte le procedure e dal programma principale. Si tratta di variabili che sono definite al di fuori delle procedure, e che sono accessibili da tutti i blocchi del programma. Per dichiarare una variabile globale, si mette la dichiarazione prima di tutte le procedure. Per esempio, se serve una variabile globale intera a si fa cosí:

class Prova {
  static int a;

  static void test() {
    int x;

    ...
  }

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

    ...
  }
}
In un certo senso, continua a valere la regola che le variabili definite all'interno di una coppia di graffe {...} sono utilizzabili solo all'interno dello stesso paio di graffe. In questo caso però la dichiarazione di a si trova tra class Prova{ e l'ultima }, per cui tutte le istruzioni di tutte le procedure (e del programma principale) possono usare questa variabile, sia per memorizzare un valore che per vedere il suo contenuto.

La situazione che si viene a creare nella memoria si può rappresentare come segue:

a
    
      
 
test
x
    
      
 
 
main
x
    
      
 

Detto a parole, la variabile a è una casella (zona di memoria) che non sta dentro il contenitore di nessuna delle procedure. Per questo tipo di variabili vale la regola che tutte le procedure e funzioni possono usare queste variabili.

Consideriamo il seguente programma Globali.java:

/*
  Esempio di variabili globali.
*/

class Globali {
  static int a;

  static void test() {
    a=a+1;
  }

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

    test();
    test();

    System.out.println("La variabile vale "+a);
  }
}

Quello che succede è che la variabile a viene creata come una variabile globale. Quindi, sia test che main possono usarla. In particolare, quando si esegue a=10 dentro main, viene messo 10 nella variabile. Quando si chiama la procedura test, si esegue l'istruzione a=a+1. Questa istruzione incrementa di 1 il valore della variabile a, e questa è ancora la variabile globale. Quando si chiama la seconda volta la procedura, il contenuto della variabile viene incrementato di nuovo. Alla fine, l'istruzione System.out.println("La variabile vale "+a); stampa il valore di a, che ora è 12.

Si noti la differenza dal programma in cui vengono dichiarate due variabili con lo stesso nome a sia dentro test che dentro main: in questo caso, si tratta di due variabili distinte, e ogni blocco di istruzioni può accedere soltanto alla sua variabile, e non a quella dell'altro blocco (anche se le due variabili hanno lo stesso nome).

Questo meccanismo consente di far passare informazioni dal programma alle procedure e viceversa: se per esempio il programma vuole mandare un intero a una procedura, può mettere il valore in una variabile globale e poi chiamare la procedura. La procedura, a sua volta, può leggere il valore che il programma ha scritto in questa variabile. Si veda per esempio il programma che stampa un certo numero di linee bianche fatto usando una variabile globale:

class Linee {
  static int lineedalasciare;

  static void lineebianche() {
    int i;

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

  public static void main(String[] args) {

    /* stampa 10 linee */
    lineedalasciare=10;
    lineebianche();

    ...

    /* stampa 20 linee */
    lineedalasciare=10;
    lineebianche();
  }
}
Quello che succede, in questo caso, è che il programma principale mette il valore 10 nella variabile lineedalasciare e poi chiama la procedura lineebianche(). Questa procedura contiene un ciclo in cui la variabile i va da 1 al contenuto della variabile lineedalasciare, che è appunto 10. In questo modo, la procedura riesce a usare un valore che è stato memorizzato dal programma principale.

Nota: il passaggio di parametri e i valori di ritorno sono anch'essi forme di comunicazione di dati fra procedure e programma. In effetti, è possibile non usare affatto gli argomenti, limitandosi a usare sempre variabili globali. Questo modo di procedere è fortemente sconsigliato, a meno che non sia realmente necessario (vedi il caso della reazione al mouse negli applet) perchè in questo modo si genera un codice difficile da leggere, cha spesso genera errori e sempre un abbassamento del voto finale.

Nota: ci sono dei casi in cui una variabile globale non è utilizzabile da una procedura. Questo problema viene analizzato nella pagina dedicata alla visibilità.