Static: Membri Condivisi tra Tutti gli Oggetti
🎯 Obiettivi della lezione
- Comprendere la differenza tra membri static e di istanza
- Creare e usare variabili static
- Creare e usare metodi static
- Capire quando usare static
- Conoscere le costanti (final)
💡 Cosa significa Static?
Un membro static appartiene alla classe e non alle singole istanze (oggetti).
Significa che è condiviso tra tutti gli oggetti della classe.
Puoi accedere a un membro static anche senza creare oggetti!
🔍 Differenza: Static vs Istanza
| Aspetto | Membri di Istanza (normali) | Membri Static |
|---|---|---|
| Appartenenza | Ogni oggetto ha la sua copia | Unica copia condivisa |
| Accesso | oggetto.membro | NomeClasse.membro |
| Creazione | Quando creiamo un oggetto | Quando viene caricata la classe |
| Serve l'oggetto? | Sì | No |
📝 Variabili Static: Esempio Base
public class Studente {
// Variabile di ISTANZA - ogni studente ha la sua
private String nome;
private int eta;
// Variabile STATIC - condivisa da tutti gli studenti
private static int numeroStudenti = 0;
// Costruttore
public Studente(String nome, int eta) {
this.nome = nome;
this.eta = eta;
numeroStudenti++; // Incremento il contatore
}
// Metodo di istanza
public void stampaInfo() {
System.out.println("Nome: " + nome + ", Età: " + eta);
}
// Metodo STATIC per accedere alla variabile static
public static int getNumeroStudenti() {
return numeroStudenti;
}
}
public class TestStudente {
public static void main(String[] args) {
// All'inizio non ci sono studenti
System.out.println("Studenti totali: " + Studente.getNumeroStudenti());
// Creo 3 studenti
Studente s1 = new Studente("Mario", 17);
Studente s2 = new Studente("Giulia", 16);
Studente s3 = new Studente("Luca", 17);
// Il contatore è aumentato!
System.out.println("Studenti totali: " + Studente.getNumeroStudenti());
// Creo un altro studente
Studente s4 = new Studente("Anna", 18);
System.out.println("Studenti totali: " + Studente.getNumeroStudenti());
}
}
🎯 Punti chiave:
- numeroStudenti è condiviso da tutti gli oggetti Studente
- Ogni volta che creiamo uno studente, il contatore aumenta
- Accediamo al metodo static con NomeClasse.metodo()
- Non serve creare un oggetto per chiamare getNumeroStudenti()
🔧 Metodi Static
Un metodo static può essere chiamato senza creare un oggetto.
I metodi static NON possono accedere a membri di istanza direttamente.
📝 Esempio: Classe Calcolatrice
public class Calcolatrice {
// Metodi static - non serve creare un oggetto Calcolatrice!
public static int somma(int a, int b) {
return a + b;
}
public static int sottrazione(int a, int b) {
return a - b;
}
public static int moltiplicazione(int a, int b) {
return a * b;
}
public static double divisione(double a, double b) {
if (b != 0) {
return a / b;
} else {
System.out.println("Errore: divisione per zero!");
return 0;
}
}
public static double potenza(double base, int esponente) {
return Math.pow(base, esponente);
}
public static double radiceQuadrata(double numero) {
if (numero >= 0) {
return Math.sqrt(numero);
} else {
System.out.println("Errore: radice di numero negativo!");
return 0;
}
}
}
public class TestCalcolatrice {
public static void main(String[] args) {
// Non serve creare un oggetto!
// Uso direttamente NomeClasse.metodo()
int risultato1 = Calcolatrice.somma(10, 5);
System.out.println("10 + 5 = " + risultato1);
int risultato2 = Calcolatrice.moltiplicazione(4, 7);
System.out.println("4 * 7 = " + risultato2);
double risultato3 = Calcolatrice.divisione(20, 4);
System.out.println("20 / 4 = " + risultato3);
double risultato4 = Calcolatrice.potenza(2, 10);
System.out.println("2^10 = " + risultato4);
double risultato5 = Calcolatrice.radiceQuadrata(144);
System.out.println("√144 = " + risultato5);
}
}
🔄 Simile alle funzioni del C!
I metodi static sono molto simili alle funzioni che usavi in C:
- Non hanno bisogno di un "oggetto"
- Prendono parametri e restituiscono risultati
- Sono utilità indipendenti
La classe Math di Java contiene solo metodi static: Math.sqrt(), Math.pow(), etc.
🚫 Limitazioni dei Metodi Static
⚠️ Un metodo static NON può:
- Accedere direttamente a variabili di istanza
- Chiamare direttamente metodi di istanza
- Usare la parola chiave this
Perché? Perché un metodo static può essere chiamato senza oggetti, quindi non sa a quale oggetto riferirsi!
public class Esempio {
private int valore; // Variabile di istanza
private static int valoreStatic; // Variabile static
// Metodo static
public static void metodoStatic() {
// valore = 10; // ERRORE! Non può accedere a variabili di istanza
valoreStatic = 10; // OK! Può accedere a variabili static
// this.valore = 5; // ERRORE! Non può usare this
}
// Metodo di istanza
public void metodoIstanza() {
valore = 10; // OK! Può accedere a variabili di istanza
valoreStatic = 10; // OK! Può accedere anche a variabili static
}
}
🔒 Costanti: final
La parola chiave final rende una variabile costante.
Una volta assegnato un valore, non può più essere modificato.
Le costanti si scrivono tipicamente in MAIUSCOLO con underscore.
public class Configurazione {
// Costanti pubbliche e static
public static final double PI_GRECO = 3.14159;
public static final int MAX_STUDENTI = 30;
public static final String NOME_SCUOLA = "Liceo Scientifico";
public static final double IVA = 0.22; // 22%
// Metodo che usa le costanti
public static double calcolaPrezzoConIva(double prezzoBase) {
return prezzoBase * (1 + IVA);
}
}
public class TestConfigrazione {
public static void main(String[] args) {
System.out.println("Scuola: " + Configurazione.NOME_SCUOLA);
System.out.println("Max studenti: " + Configurazione.MAX_STUDENTI);
System.out.println("Pi greco: " + Configurazione.PI_GRECO);
double prezzo = 100;
double prezzoFinale = Configurazione.calcolaPrezzoConIva(prezzo);
System.out.println("Prezzo base: €" + prezzo);
System.out.println("Prezzo con IVA: €" + prezzoFinale);
// Configurazione.IVA = 0.30; // ERRORE! È final!
}
}
🏦 Esempio Completo: Classe BancaCentrale
public class BancaCentrale {
// Costanti
public static final double TASSO_INTERESSE = 0.02; // 2%
public static final double LIMITE_PRELIEVO = 500.0;
// Variabile static per contare i conti
private static int numeroConti = 0;
// Attributi di istanza
private String numeroConto;
private String intestatario;
private double saldo;
// Costruttore
public BancaCentrale(String intestatario, double saldoIniziale) {
numeroConti++;
this.numeroConto = "IT" + numeroConti;
this.intestatario = intestatario;
this.saldo = saldoIniziale;
}
// Metodo di istanza
public void applicaInteressi() {
double interessi = saldo * TASSO_INTERESSE;
saldo += interessi;
System.out.println("Interessi applicati: €" + interessi);
}
// Metodo di istanza
public boolean preleva(double importo) {
if (importo > LIMITE_PRELIEVO) {
System.out.println("Impossibile! Limite prelievo: €" + LIMITE_PRELIEVO);
return false;
}
if (saldo >= importo) {
saldo -= importo;
System.out.println("Prelevati €" + importo);
return true;
} else {
System.out.println("Saldo insufficiente!");
return false;
}
}
// Metodo di istanza
public void stampaSaldo() {
System.out.println(intestatario + " - Saldo: €" + saldo);
}
// Metodo static
public static int getNumeroConti() {
return numeroConti;
}
// Metodo static per convertire valuta
public static double convertiInDollari(double euro, double tassioCambio) {
return euro * tassioCambio;
}
}
public class TestBanca {
public static void main(String[] args) {
System.out.println("Conti totali: " + BancaCentrale.getNumeroConti());
System.out.println("Tasso interesse: " + (BancaCentrale.TASSO_INTERESSE * 100) + "%");
System.out.println();
BancaCentrale conto1 = new BancaCentrale("Mario Rossi", 1000);
BancaCentrale conto2 = new BancaCentrale("Giulia Bianchi", 5000);
System.out.println("Conti totali: " + BancaCentrale.getNumeroConti());
System.out.println();
conto1.stampaSaldo();
conto1.applicaInteressi();
conto1.stampaSaldo();
System.out.println();
conto1.preleva(300); // OK
conto1.preleva(600); // Supera il limite!
System.out.println();
// Uso metodo static per conversione
double euro = 1000;
double dollari = BancaCentrale.convertiInDollari(euro, 1.10);
System.out.println("€" + euro + " = $" + dollari);
}
}
✏️ Esercizi Guidati
Esercizio 1: Contatore Auto
FACILEObiettivo: Creare una classe Auto che conta quante auto sono state create.
Requisiti:
- Attributi di istanza: marca, modello
- Variabile static: numeroAuto (contatore)
- Costruttore che incrementa il contatore
- Metodo static getNumeroAuto()
- Nel main, crea 5 auto e stampa il totale
Esercizio 2: Classe Matematica
MEDIOObiettivo: Creare una classe con metodi static per operazioni matematiche.
Requisiti:
- Metodo static massimo(int a, int b) che restituisce il maggiore
- Metodo static minimo(int a, int b)
- Metodo static pari(int n) che restituisce true se pari
- Metodo static fattoriale(int n)
- Costante E_NEPERO = 2.71828
💪 Esercizi da Svolgere
Esercizio 3: Convertitore Unità
FACILECrea una classe ConvertitoreUnita con metodi static per:
- kmInMiglia(double km)
- celsiusInFahrenheit(double celsius)
- kgInLibbre(double kg)
Esercizio 4: Classe Prodotto con Codice
MEDIOCrea una classe Prodotto che assegna automaticamente un codice progressivo:
- Variabile static per il contatore
- Attributo di istanza: codice (generato automaticamente)
- Il codice deve essere "PROD001", "PROD002", etc.
Esercizio 5: Validatore
MEDIOCrea una classe Validatore con metodi static per validare:
- isEmailValida(String email) - controlla che contenga @ e .
- isCodiceFiscaleValido(String cf) - controlla che sia lungo 16 caratteri
- isTelefonoValido(String tel) - controlla che sia lungo 10 cifre
🎯 Concetti Chiave da Ricordare
- static = appartiene alla classe, non agli oggetti
- Variabili static sono condivise tra tutti gli oggetti
- Metodi static si chiamano con NomeClasse.metodo()
- Metodi static NON possono accedere a membri di istanza
- final = costante, non modificabile
- Costanti: public static final NOME_COSTANTE
- La classe Math usa solo metodi static
📚 Quando Usare Static?
✅ Usa static per:
- Metodi di utilità (come Calcolatrice, Validatore)
- Contatori condivisi
- Costanti (sempre con final)
- Factory methods
❌ NON usare static per:
- Dati specifici di ogni oggetto
- Metodi che devono accedere a attributi di istanza
- Quando hai bisogno del polimorfismo (lo vedremo)