Introduzione alle variabili in Java
Le variabili in Java sono contenitori che permettono di memorizzare valori in memoria durante l’esecuzione di un programma. Ogni variabile ha un tipo di dato, un nome e un valore, e il tipo determina quali operazioni sono possibili su quel valore. Comprendere come funzionano variabili e tipi di dato è fondamentale per scrivere codice corretto, leggibile e performante.
In questa guida vedrai come dichiarare e inizializzare variabili, quali tipi di dato mette a disposizione Java, come funzionano le conversioni di tipo, come definire costanti e come lo scope influenza la visibilità delle variabili nel codice.
Dichiarazione e inizializzazione delle variabili
Per dichiarare una variabile in Java devi specificare il tipo e il nome. Puoi anche assegnare subito un valore iniziale. La dichiarazione indica al compilatore quale spazio di memoria riservare e come interpretare i dati memorizzati.
- Dichiarazione semplice: tipo seguito dal nome, per esempio int eta;
- Dichiarazione con inizializzazione: tipo, nome e valore, per esempio int eta = 30;
- È buona pratica usare nomi descrittivi, come numeroClienti o prezzoTotale;
- Ogni variabile ha un tipo statico che non cambia durante l’esecuzione del programma.
public class DichiarazioneVariabili {
public static void main(String[] args) {
int eta; // dichiarazione
eta = 25; // assegnazione successiva
double salario = 1500.5; // dichiarazione e inizializzazione
String nome = "Luca"; // variabile di tipo reference
System.out.println("Nome: " + nome);
System.out.println("Età: " + eta);
System.out.println("Salario: " + salario);
}
}
Tipi di dato primitivi per le variabili Java
I tipi di dato primitivi rappresentano valori semplici e sono memorizzati direttamente nello stack. Java definisce otto tipi primitivi, ognuno con dimensioni e intervallo ben precisi. Sono efficienti in termini di memoria e prestazioni e non sono oggetti.
- byte: 8 bit, valori compresi tra -128 e 127. Utile per dati molto piccoli.
- short: 16 bit, valori compresi tra -32.768 e 32.767. Poco usato nel codice moderno.
- int: 32 bit, valori circa tra -2 miliardi e +2 miliardi. È il tipo intero più usato.
- long: 64 bit, per interi molto grandi. Richiede il suffisso L nei letterali, per esempio 100L.
- float: 32 bit in virgola mobile, precisione limitata. Richiede il suffisso f, per esempio 3.14f.
- double: 64 bit in virgola mobile, è il tipo predefinito per i numeri con la virgola.
- boolean: rappresenta solo due valori, true o false. Usato nelle condizioni logiche.
- char: 16 bit, rappresenta un singolo carattere Unicode, per esempio ‘A’ o ‘€’.
public class TipiPrimitiviDemo {
public static void main(String[] args) {
byte b = 100;
short s = 30000;
int i = 2000000000;
long l = 9000000000L;
float f = 3.14f;
double d = 3.1415926535;
boolean attivo = true;
char simbolo = 'A';
System.out.println("byte: " + b);
System.out.println("short: " + s);
System.out.println("int: " + i);
System.out.println("long: " + l);
System.out.println("float: " + f);
System.out.println("double: " + d);
System.out.println("boolean: " + attivo);
System.out.println("char: " + simbolo);
}
}
Tipi di dato non primitivi e riferimenti
I tipi di dato non primitivi, detti anche reference, non contengono direttamente il valore ma un riferimento a un oggetto nello heap. Sono più flessibili dei primitivi e permettono di modellare strutture dati complesse, ma introducono un overhead maggiore. Per ulteriori dettagli, consulta la Java SE API Documentation.
- String: rappresenta una sequenza di caratteri. È immutabile, quindi ogni modifica crea un nuovo oggetto.
- Array: collezione indicizzata di elementi dello stesso tipo, con dimensione fissa stabilita alla creazione.
- Class e oggetti: ogni classe definisce un nuovo tipo reference. Le istanze di classe permettono di raggruppare dati e comportamenti.
public class TipiNonPrimitiviDemo {
public static void main(String[] args) {
String messaggio = "Benvenuto in Java";
int[] numeri = new int[3];
numeri[0] = 10;
numeri[1] = 20;
numeri[2] = 30;
Persona p = new Persona("Anna", 28);
System.out.println(messaggio);
System.out.println("Primo elemento dell'array: " + numeri[0]);
System.out.println("Persona: " + p.nome + ", età " + p.eta);
}
}
class Persona {
String nome;
int eta;
Persona(String nome, int eta) {
this.nome = nome;
this.eta = eta;
}
}
Conversione di tipi e casting delle variabili
La conversione di tipi, o casting, permette di trasformare un valore da un tipo a un altro compatibile. In Java esistono conversioni implicite, eseguite automaticamente dal compilatore, e conversioni esplicite, che richiedono una sintassi specifica. È importante conoscere i casi in cui si possono perdere informazioni. Per approfondimenti sui tipi di dato e le conversioni, fai riferimento alla documentazione ufficiale Oracle.
- Casting implicito o widening: da un tipo più piccolo a uno più grande, per esempio da int a long.
- Casting esplicito o narrowing: da un tipo più grande a uno più piccolo, per esempio da double a int.
- Il casting esplicito può causare perdita della parte decimale o overflow sui tipi interi.
public class CastingDemo {
public static void main(String[] args) {
int i = 100;
long l = i; // widening implicito
double d = l; // widening implicito
double valore = 1234.56;
int tagliato = (int) valore; // narrowing esplicito, parte decimale persa
int grande = 130;
byte piccolo = (byte) grande; // overflow, il valore cambia in modo inatteso
System.out.println("long: " + l);
System.out.println("double: " + d);
System.out.println("int da double: " + tagliato);
System.out.println("byte da int: " + piccolo);
}
}
Costanti con la parola chiave final
La parola chiave final indica che una variabile non può essere riassegnata dopo la sua inizializzazione. Quando viene combinata con static e usata per valori immutabili, si parla di costante. Le costanti rendono il codice più chiaro, evitano errori di modifica accidentale e centralizzano la gestione dei valori fissi.
- Una variabile final deve essere inizializzata una sola volta.
- Le costanti di classe si dichiarano di solito public static final con nome in maiuscolo.
- final su un riferimento impedisce la riassegnazione, ma non blocca la modifica interna dell’oggetto.
public class CostantiDemo {
public static final double IVA = 0.22;
private final String codiceCliente;
public CostantiDemo(String codiceCliente) {
this.codiceCliente = codiceCliente;
}
public void stampaDati(double importo) {
double totale = importo * (1 + IVA);
System.out.println("Cliente: " + codiceCliente);
System.out.println("Totale con IVA: " + totale);
}
public static void main(String[] args) {
CostantiDemo demo = new CostantiDemo("CL001");
demo.stampaDati(100);
}
}
Scope delle variabili
Lo scope di una variabile definisce in quale porzione di codice la variabile è visibile e utilizzabile. Gestire correttamente lo scope aiuta a evitare errori, ridurre le dipendenze tra parti di codice e migliorare la manutenibilità di un’applicazione.
- Variabili locali: dichiarate all’interno di metodi o blocchi, esistono solo per la durata del blocco.
- Variabili di istanza: dichiarate nella classe, ma fuori dai metodi. Ogni oggetto ha la propria copia.
- Variabili statiche o di classe: dichiarate con static. Esiste una sola copia condivisa da tutte le istanze.
public class ScopeDemo {
private int contatoreIstanza; // variabile di istanza
private static int contatoreGlobale; // variabile di classe
public void esegui() {
int locale = 0; // variabile locale al metodo
for (int i = 0; i < 5; i++) {
locale++;
contatoreIstanza++;
contatoreGlobale++;
}
System.out.println("locale: " + locale);
System.out.println("istanza: " + contatoreIstanza);
System.out.println("globale: " + contatoreGlobale);
}
public static void main(String[] args) {
ScopeDemo s1 = new ScopeDemo();
ScopeDemo s2 = new ScopeDemo();
s1.esegui();
s2.esegui();
}
}
Esempi pratici con blocchi di codice
Questi esempi riassumono i concetti visti finora mostrando l’uso combinato di tipi primitivi, tipi reference, casting e costanti in un semplice programma di esempio.
public class RiepilogoVariabili {
public static final double CAMBIO_EURO_DOLLARO = 1.1;
public static void main(String[] args) {
int quantita = 5;
double prezzoUnitario = 19.99;
double totaleEuro = quantita * prezzoUnitario;
double totaleDollari = totaleEuro * CAMBIO_EURO_DOLLARO;
int totaleArrotondato = (int) totaleDollari; // casting esplicito
String descrizione = "Ordine di " + quantita + " pezzi";
System.out.println(descrizione);
System.out.println("Totale in euro: " + totaleEuro);
System.out.println("Totale in dollari: " + totaleDollari);
System.out.println("Totale arrotondato: " + totaleArrotondato);
}
}
public class PassaggioPerValore {
public static void incrementaInt(int valore) {
valore = valore + 1;
}
public static void incrementaContatore(Contatore c) {
c.valore = c.valore + 1;
}
public static void main(String[] args) {
int numero = 10;
incrementaInt(numero);
System.out.println("Dopo incrementaInt: " + numero);
Contatore c = new Contatore();
c.valore = 10;
incrementaContatore(c);
System.out.println("Dopo incrementaContatore: " + c.valore);
}
}
class Contatore {
int valore;
}
Conclusione e articoli correlati
La gestione corretta di variabili e tipi di dato è alla base di ogni applicazione Java, dalle utility da riga di comando ai sistemi distribuiti complessi. Sapere quando usare tipi primitivi o reference, come effettuare conversioni di tipo in modo sicuro, come definire costanti e come sfruttare lo scope ti permette di scrivere codice più chiaro, robusto e facile da testare.
Per completare la panoramica sul modello dei tipi di Java è utile approfondire anche la gestione della memoria, le collezioni e i generics, oltre alle tecniche per scrivere codice immutabile e thread safe.
- Gestione della memoria in Java: stack, heap e garbage collector.
- Collezioni Java, con particolare attenzione a liste, insiemi e mappe.
- Lettura e scrittura di file in Java con le API di input e output.
- Programmazione generica con tipi parametrizzati per scrivere codice riutilizzabile.
- Uso efficiente delle stringhe e di oggetti simili a value object per modellare il dominio.
- Introduzione alla programmazione concorrente e alla gestione dei thread in Java.

Lascia un commento