1. Array di tipo String
E, in breve, vorremmo parlare di un array di tipo String.
Come abbiamo già detto, un array può essere di qualsiasi tipo. Quindi si può creare un array di tipo String. Ecco come apparirebbe il codice se dovessimo scrivere un programma che “inserisce da tastiera 10 righe e le stampa a schermo in ordine inverso”.
String[] array = new String[10]; // Creiamo un oggetto array di 10 elementi
for (int i = 0; i < 10; i++) // Ciclo da 0 a 9
{
array[i] = console.nextLine(); // Leggiamo una riga da tastiera e la salviamo nella cella dell'array
}
for (int i = 9; i >= 0; i--) // Ciclo da 9 a 0
{
System.out.println(array[i]); // Stampiamo a schermo la cella corrente dell'array
}
Il codice praticamente non è cambiato! Al momento della creazione dell’array abbiamo solo sostituito il tipo int con String. Per il resto è tutto esattamente uguale!
Introduzione a null
Ecco un indovinello — cosa c’è nelle celle di ognuno di questi array subito dopo la creazione?
int[] numbers = new int[10];
String[] strings = new String[10];
User[] users = new User[10];
Ragionandoci, probabilmente le celle di numbers contengono 0. Corretto.
Allora, per la stessa logica, le celle di strings dovrebbero essere riempite con stringhe vuote — "". Supponiamo.
E con cosa sono riempite le celle dell’array users? Con User “vuoti”?
Qui sta il trucco: non per ogni tipo di dato esiste un “valore predefinito”. Perciò i creatori di Java hanno ideato una costante speciale — null. null è un riferimento vuoto. Quando si crea una variabile di tipo oggetto, il suo valore iniziale è null: un riferimento a nulla, assenza di riferimento.
String name; // name contiene null
name = "Alex"; // name contiene un riferimento all'oggetto/stringa "Alex"
name = null; // name contiene null
Lavorare con null
Non si possono chiamare metodi su un oggetto se il riferimento è null — l’oggetto non esiste! Con questo codice il programma terminerà con un errore:
String name; // name contiene null
String upperName = name.toUpperCase(); // Si verificherà un errore NullPointerException: name == null
Per quanto riguarda il nostro “indovinello”, la risposta è la seguente:
int[] numbers = new int[10]; // {0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
String[] strings = new String[10]; // {null, null, null, null, null, null, null, null, null, null}
User[] users = new User[10]; // {null, null, null, null, null, null, null, null, null, null}
Solo i tipi primitivi hanno un “valore predefinito”. Tutti gli altri tipi, per impostazione predefinita, valgono null. Il valore iniziale di String non è la stringa vuota. Così va la vita.
2. Array di tipo String in memoria
Figura 1. Come un oggetto String è disposto in memoria:

Attenzione: il testo della stringa non è memorizzato direttamente nella variabile; per esso viene allocato un blocco di memoria separato. Nella variabile di tipo String è memorizzato l’indirizzo (riferimento) all’oggetto con il testo.
Figura 2. Come un array di interi è disposto in memoria:

Avete già visto anche questa immagine.
Figura 3. Come in memoria è disposto un array di stringhe:

A sinistra vediamo la variabile-array di tipo String[] (contiene l’indirizzo dell’oggetto array).
Al centro — l’oggetto array di tipo String.
A destra — gli oggetti stringa che contengono dei testi.
Nelle celle dell’oggetto array di tipo String non sono memorizzate le stringhe (i testi) stesse, ma i loro indirizzi (riferimenti). Proprio come nelle variabili di tipo String sono memorizzati gli indirizzi delle stringhe (del testo).
3. Inizializzazione rapida di un array in Java
Gli array sono molto utili, quindi gli sviluppatori di Java hanno cercato di rendere il lavoro con essi il più comodo possibile. E la prima cosa che hanno fatto è semplificare l’inizializzazione dell’array, ovvero l’inserimento dei valori iniziali.
Infatti molto spesso, oltre ai dati che il programma legge da qualche parte, per funzionare gli servono anche dati interni. Per esempio, dobbiamo memorizzare in un array le durate di tutti i mesi. Il codice potrebbe essere così:
int[] months = new int[12];
months[0] = 31; // gennaio
months[1] = 28; // febbraio
months[2] = 31; // marzo
months[3] = 30; // aprile
months[4] = 31; // maggio
months[5] = 30; // giugno
months[6] = 31; // luglio
months[7] = 31; // agosto
months[8] = 30; // settembre
months[9] = 31; // ottobre
months[10] = 30; // novembre
months[11] = 31; // dicembre
Ma c’è un modo per scriverlo più corto — grazie ai creatori di Java:
// lunghezze dei mesi dell'anno
int[] months = new int[] { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
Si possono semplicemente elencare tutti i valori separati da virgole!
Si scopre che il compilatore può determinare il tipo del contenitore (l’oggetto array) in base al tipo della variabile array. E per determinare la lunghezza dell’array — semplicemente conta il numero di elementi racchiusi tra parentesi graffe.
Quindi questo codice si può scrivere ancora più corto:
// lunghezze dei mesi dell'anno
int[] months = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
Non è una bellezza? 🙂 Questa sintassi si chiama “inizializzazione rapida dell’array”. Tra l’altro, funziona non solo per il tipo int...
// nomi dei mesi dell'anno
String[] months = { "Gennaio", "Febbraio", "Marzo", "Aprile", "Maggio", "Giugno", "Luglio", "Agosto", "Settembre", "Ottobre", "Novembre", "Dicembre" };
4. Il ciclo for-each
Iterare su tutti gli elementi di un array è così frequente che per esso è stato introdotto un ciclo speciale — for-each. Si scrive così:
for (int score : scores)
{
System.out.println("Punti: " + score);
}
Qui il ciclo scorre gli elementi da solo — nessun indice manuale. Però non si possono modificare gli elementi direttamente (nella variabile del ciclo è conservata solo una copia del valore); è invece molto comodo semplicemente “passare” sull’array.
Il compilatore trasformerà il codice del ciclo for-each nel codice seguente:
for (int i = 0; i < scores.length; i++)
{
int score = scores[i];
System.out.println("Punti: " + score);
}
Quindi, nessuna magia. Ora è chiaro perché non potete modificare gli elementi dell’array tramite la variabile score.
Scriviamo un altro esempio: troviamo la somma di tutti i punti.
int sum = 0;
for (int score : scores)
{
sum += score;
}
System.out.println("Somma di tutti i punti: " + sum);
Quando usare quale ciclo?
- Se serve l’indice o è necessario modificare gli elementi — ciclo for.
- Se bisogna solo scorrere i valori — for-each è più veloce e pulito.
5. Modifica degli elementi dell’array
E se dobbiamo aumentare ogni voto di 1 punto (per esempio, per buon comportamento)? Qui serve il classico for con indice, perché solo così possiamo modificare i valori nell’array.
Esempio: aumentare ogni elemento di 1
for (int i = 0; i < grades.length; i++) {
grades[i] = grades[i] + 1;
}
Dopo l’esecuzione di questo codice, nell’array grades ci saranno nuovi valori.
Perché non si può farlo con for-each?
for (int grade : grades) {
grade = grade + 1; // Non funziona!
}
Questo codice non modificherà l’array, perché grade è una copia del valore dell’array, non un riferimento all’elemento stesso.
6. Calcoli basati su un array
Gli array sono spesso usati per i calcoli: somma, media, massimo, minimo e così via.
Esempio: somma di tutti gli elementi dell’array
int sum = 0;
for (int i = 0; i < grades.length; i++) {
sum += grades[i]; // è lo stesso di sum = sum + grades[i];
}
System.out.println("Somma dei voti: " + sum);
Esempio: ricerca del valore massimo
int max = grades[0]; // iniziamo dal primo elemento
for (int i = 1; i < grades.length; i++) {
if (grades[i] > max) {
max = grades[i];
}
}
System.out.println("Voto massimo: " + max);
Esempio: ricerca del valore minimo
int min = grades[0]; // iniziamo dal primo elemento
for (int i = 1; i < grades.length; i++) {
if (grades[i] < min) {
min = grades[i];
}
}
System.out.println("Voto minimo: " + min);
Esempio: calcolo della media aritmetica
int sum = 0;
for (int i = 0; i < grades.length; i++) {
sum += grades[i];
}
double average = (double) sum / grades.length; // è obbligatorio effettuare il cast a double!
System.out.println("Voto medio: " + average);
Attenzione: per ottenere un numero con la virgola, bisogna effettuare esplicitamente il cast della somma a double prima della divisione.
7. Esercizi pratici
Input di un array da tastiera
Spesso è necessario riempire un array con valori inseriti dall’utente. Per questo usiamo la classe Scanner e un ciclo.
Scanner console = new Scanner(System.in);
int n = 5; // dimensione dell'array
int[] numbers = new int[n];
System.out.println("Inserisci " + n + " numeri:");
for (int i = 0; i < n; i++) {
numbers[i] = console.nextInt();
}
System.out.println("Hai inserito:");
for (int i = 0; i < n; i++) {
System.out.println(numbers[i]);
}
Stampa dell’array in ordine inverso
A volte bisogna stampare gli elementi dell’array dalla fine (per esempio, per sapere chi è entrato per ultimo nella stanza).
for (int i = grades.length - 1; i >= 0; i--) {
System.out.println("Voto n. " + (i + 1) + ": " + grades[i]);
}
8. Errori tipici nel lavoro con array monodimensionali
Errore n. 1: uscita dai limiti dell’array
Il problema più comune è tentare di accedere a un elemento inesistente. In Java questo porta all’eccezione ArrayIndexOutOfBoundsException. Ricordate: l’ultimo indice valido è arr.length - 1.
int[] arr = new int[5];
System.out.println(arr[5]); // Errore! Indici da 0 a 4.
Errore n. 2: dimenticare di inizializzare l’array
Si dichiara la variabile, ma non si crea l’array:
int[] arr;
arr[0] = 5; // Errore! L'array non è stato creato.
Bisogna creare l’array con new:
arr = new int[10];
Errore n. 3: tentare di modificare gli elementi dell’array tramite for-each
Nel ciclo for-each la variabile è una copia del valore, non un riferimento all’elemento:
for (int x : arr) {
x = 100; // Non modifica l'array!
}
Per modificare i valori, usate un for classico con indice.
Errore n. 4: uso scorretto della lunghezza dell’array
A volte si confonde la lunghezza dell’array con l’ultimo indice:
for (int i = 0; i <= arr.length; i++) { // Errore! Dovrebbe essere i < arr.length
// ...
}
Questo codice porterà a un’uscita dai limiti.
Errore n. 5: conversione implicita dei tipi
Se l’array è di tipo int, non si può assegnare direttamente un valore di tipo double:
int[] arr = new int[3];
arr[0] = 3.14; // Errore! 3.14 è un double.
GO TO FULL VERSION