Menu

Modificatori di accesso in Java: public, private, protected, default

Come i quattro livelli di accesso di Java, cioè public, private, protected e package-private, controllano cosa può vedere e toccare il resto del codice.

Questa pagina include editor eseguibili: modifica, esegui e vedi subito l'output.

Chi può toccare il tuo codice

Un modificatore di accesso è una parola chiave davanti a una classe, un campo, un metodo o un costruttore che decide chi altro può usarlo. È la base dell'incapsulamento: nascondi i dettagli interni di una classe ed esponi solo le parti che ti fidi a far chiamare ad altro codice.

Java ha quattro livelli, dal più aperto al più chiuso: public, protected, default (nessuna parola chiave) e private. Se li scegli bene, una classe diventa sicura da modificare in futuro, perché niente al di fuori dipende da dettagli che non hai mai promesso di mantenere.

private: visibile solo dentro la classe

private è il livello più stretto. Un membro private può essere toccato solo dal codice scritto nella stessa classe: non dalle sottoclassi, non da altre classi dello stesso package, da nessuno. È qui che dovrebbe stare la maggior parte dei tuoi campi.

balance è private, quindi l'unico modo per cambiarlo è passare da deposit, che rifiuta gli importi negativi. Se balance fosse public, qualsiasi codice potrebbe scrivere account.balance = -9999 e saltare del tutto il controllo. Quel controllo è proprio il motivo per cui si nasconde il campo.

Prova ad aggiungere account.balance = 500; in main e otterrai un errore di compilazione: balance has private access in BankAccount.

public: visibile ovunque

public è l'estremo opposto: chiunque, ovunque, può usare il membro. I metodi che altro codice deve chiamare sono di solito public. Lo è anche la classe stessa quando deve essere raggiungibile da altri package.

Lo schema comune, a volte chiamato API pubblica di una classe, è campi private, metodi public. I campi contengono uno stato che nessun altro dovrebbe toccare; i metodi sono le porte controllate per entrare e uscire. getBalance e deposit qui sopra sono esattamente questo.

default (package-private): nessuna parola chiave

Se non scrivi nessun modificatore, ottieni l'accesso default, detto anche package-private. Il membro è visibile a tutte le classi dello stesso package e invisibile a tutto ciò che sta fuori. Non esiste una parola chiave per questo livello: la sua assenza è il livello.

class Invoice {       // nessun modificatore -> visibile solo in questo package
    int amount;       // nessun modificatore -> campo package-private
}

Qui cascano molti principianti: omettere public non rende qualcosa private, lo rende package-private. Un campo che volevi tenere segreto resta leggibile e scrivibile da qualsiasi classe che si trovi nello stesso package. Se vuoi nasconderlo davvero, devi scrivere private in modo esplicito.

L'accesso default è davvero utile per classi di supporto che sono un dettaglio implementativo di un package: non le esporti, ma le classi che collaborano all'interno del package possono comunque usarle liberamente.

protected: package più sottoclassi

protected è un gradino più permissivo di default. Un membro protected è visibile ovunque lo sia default (lo stesso package) e in più alle sottoclassi, anche a quelle in un altro package. È pensato per ciò che vuoi condividere con le classi che estendono la tua, ma non con tutto il mondo.

Dog accede a name e sound() perché sono protected e Dog è una sottoclasse. Il codice esterno che non è una sottoclasse e non sta nel package continua a non poterli toccare. Usa protected quando progetti una classe pensata per essere estesa; altrimenti preferisci private.

I quattro livelli a colpo d'occhio

Ecco il quadro completo, dal più restrittivo al più aperto:

ModificatoreStessa classeStesso packageSottoclasse (altro package)Ovunque
privatesìnonono
defaultsìsìnono
protectedsìsìsìno
publicsìsìsìsì

Una regola pratica semplice: parti da private e allarga solo quando qualcosa ha davvero bisogno di un accesso più ampio. È molto più facile allargare l'accesso in seguito che restringerlo quando altro codice ha già iniziato a dipendere da un membro.

Modificatori sulle classi

I modificatori di accesso si applicano anche alle classi, non solo ai membri, ma una classe top-level (cioè non annidata in un'altra) può essere solo public o default. Non puoi scrivere una classe top-level private o protected.

public class Order { ... }   // raggiungibile da qualsiasi package
class LineItem { ... }       // default: solo questo package può vederla

Una classe top-level public deve stare in un file che porta il suo nome (Order.java). Le classi annidate, invece, possono usare tutti e quattro i modificatori: ecco perché gli esempi qui sopra potevano marcare le classi interne come private o default. Un dettaglio sottile: un metodo public che restituisce un tipo package-private non è molto utile a chi lo chiama da fuori, quindi mantieni coerente la tua superficie pubblica.

Prossimo passo: i membri static

Finora ogni campo e metodo qui appartiene a un'istanza: crei un oggetto con new e poi chiami i metodi su di esso. A volte però un valore o un comportamento appartiene alla classe nel suo insieme ed è condiviso da tutte le istanze, come un contatore di quanti oggetti esistono. È a questo che serve la parola chiave static, ed è il prossimo argomento.

Domande frequenti

Quali sono i quattro modificatori di accesso in Java?

public, private, protected e il default (nessuna parola chiave, detto anche package-private). public è visibile ovunque, private solo nella stessa classe, protected nel package più le sottoclassi, e default solo nello stesso package.

Qual è la differenza tra public e private in Java?

public significa che qualsiasi codice, ovunque, può accedere al membro. private significa che solo il codice nella stessa classe può farlo: sottoclassi e altre classi non lo vedono nemmeno. Di solito rendi i campi private e li esponi tramite metodi public.

Cosa significa quando un campo Java non ha modificatore di accesso?

Nessuna parola chiave significa accesso default (package-private): il membro è visibile a tutte le classi dello stesso package, ma invisibile al di fuori. È più restrittivo di public ma più permissivo di private, ed è facile ometterlo per sbaglio, quindi usalo in modo consapevole.

Illustrazione dei linguaggi di programmazione di Coddy

Impara a programmare con Coddy

INIZIA