W3docs

Modificatori Non-Access in Java

Usa i modificatori non-access di Java — static, final, abstract, synchronized, transient, volatile — e cosa controlla ciascuno.

I modificatori di accesso di Java — public, protected, private — controllano chi può vedere un membro. I modificatori non-access controllano come si comporta. Sono un piccolo insieme di parole chiave che cambiano la proprietà, la mutabilità, il threading, la serializzazione e alcune altre cose. Questo capitolo è la mappa; ogni modificatore ha un capitolo o una sezione più approfondita altrove.

L'elenco completo

ModificatoreSi applica aCosa fa
staticcampi, metodi, classi annidate, blocchiAppartiene alla classe, non alle istanze
finalclassi, metodi, campi, parametri, variabili localiNon può essere riassegnato/sovrascritto/esteso
abstractclassi, metodiNessun corpo / non può essere istanziato; deve essere implementato da una sottoclasse
synchronizedmetodi, blocchiSolo un thread alla volta può eseguirlo su un dato lock
volatilecampiLe letture/scritture non vengono memorizzate nella cache locale del thread
transientcampiIgnorato dalla serializzazione predefinita
nativemetodiL'implementazione risiede in codice non-Java (di solito C/C++)
strictfpclassi, metodiForza un comportamento rigoroso IEEE-754 per i float (principalmente storico)
defaultmetodi di interfacciaFornisce un corpo predefinito in un'interfaccia
sealed / non-sealedclassi, interfacceLimita le classi che possono estendere (Java 17+)

Incontrerai static, final, abstract e default costantemente. Gli altri li vedrai solo quando emerge il problema specifico.

static — appartiene alla classe

Un membro static è associato alla classe stessa, non a una singola istanza:

public class Counter {
  int instanceCount;          // one per Counter object
  static int classCount;      // one shared by everyone
}

static è così comune da avere un capitolo dedicato — vedi java-static.

final — non può cambiare

final significa "questo binding è fisso dopo che è stato impostato." Si applica a diverse cose:

final int MAX = 100;          // local variable cannot be reassigned
public final class Money {}   // class cannot be extended
public final void close() {}  // method cannot be overridden
private final int balance;    // field assigned once, then immutable

final è la base delle costanti (static final), degli oggetti immutabili e di un design dell'ereditarietà sicuro. Trattazione completa in java-final.

abstract — non ha corpo, deve essere implementato

abstract applicato a una classe significa "non puoi istanziarla direttamente — solo le sottoclassi possono farlo." Applicato a un metodo, significa "nessun corpo qui — ogni sottoclasse concreta deve fornirne uno":

public abstract class Shape {
  public abstract double area();      // no body
}

public class Circle extends Shape {
  double r;
  public double area() { return Math.PI * r * r; }
}

new Shape() è un errore di compilazione; new Circle() funziona. Trattato in classi astratte.

synchronized — un thread alla volta

Quando due thread potrebbero chiamare lo stesso metodo sullo stesso oggetto, contrassegnare il metodo con synchronized garantisce che solo uno venga eseguito alla volta:

public synchronized void deposit(int amount) {
  balance += amount;
}

Questa è la forma più semplice di locking. C'è un'intera sezione sulla concorrenza più avanti nel libro; per ora, riconosci che la parola chiave esiste e cosa fa in linea generale. Vedi synchronization per la storia completa.

volatile — visibile tra i thread

Senza volatile, i thread possono memorizzare nella cache il valore di un campo. Le letture in un thread potrebbero non vedere mai le scritture di un altro:

private volatile boolean stopped = false;

volatile forza ogni lettura a provenire dalla memoria principale e ogni scrittura ad andare nella memoria principale. È il cugino leggero di synchronized per campi semplici di tipo flag — vedi volatile per i dettagli sul modello di memoria.

transient — salta durante la serializzazione

La serializzazione di oggetti integrata di Java (Serializable) scrive ogni campo per impostazione predefinita. transient dice "non includere questo" — tipicamente usato per cache, valori calcolati o cose che non hanno senso al di fuori del programma in esecuzione:

public class Session {
  String userId;
  transient String passwordHash;     // not serialized
}

Il codice moderno usa i serializzatori JSON più di Serializable, ma la parola chiave è ancora utile nelle librerie che la utilizzano. Maggiori informazioni in serialization.

native — implementato altrove

native è per i metodi il cui corpo si trova in un altro linguaggio (C/C++ tramite JNI). Raramente li scrivi tu stesso; li vedi solo nelle librerie di basso livello:

public native int currentTimeMillis();

strictfp — aritmetica in virgola mobile rigorosa

In origine, strictfp forzava un'aritmetica in virgola mobile IEEE-754 prevedibile tra le piattaforme. A partire da Java 17, tutta la matematica in virgola mobile è implicitamente rigorosa, il che rende la parola chiave un no-op. Puoi per lo più ignorarla; persiste nelle basi di codice più vecchie.

default — sui metodi di interfaccia

All'interno di un'interfaccia, default consente di fornire un corpo per un metodo invece di lasciarlo astratto:

public interface Greeter {
  default String greet(String name) {
    return "Hello, " + name;
  }
}

Senza default, un metodo di interfaccia non ha corpo e ogni classe che la implementa deve scrivere il proprio. Trattazione completa in default methods.

sealed e non-sealed

Una classe sealed nomina l'elenco esatto delle classi autorizzate ad estenderla. Le sottoclassi devono poi scegliere di essere final, sealed o non-sealed:

public sealed class Shape permits Circle, Square { }
public final class Circle extends Shape { }
public non-sealed class Square extends Shape { }

Utile per gerarchie di tipi chiuse — vedi sealed classes.

Combinare i modificatori

Di solito è possibile combinare liberamente i modificatori, nel seguente ordine convenzionale:

public  static  final   int MAX = 100;
private static  volatile int counter;
protected abstract       void onInit();

Alcune combinazioni sono illegali: un metodo non può essere sia abstract che final, sia abstract che private, né sia abstract che static. Il compilatore ti avviserà quando hai superato il limite.

Un esempio pratico

java— editable, runs on the server

Cosa c'è dopo

I prossimi due capitoli approfondiscono i due modificatori che userai più spesso: static per i membri a livello di classe, poi final per l'immutabilità. Leggili in ordine.

Esercitati

Pratica
Quale modificatore non-access indica che un membro di classe appartiene alla classe stessa piuttosto che a ogni singola istanza?
Quale modificatore non-access indica che un membro di classe appartiene alla classe stessa piuttosto che a ogni singola istanza?
Was this page helpful?