Best Practice per la Denominazione in Java
Regole pratiche di denominazione Java per pacchetti, classi, metodi, variabili e costanti.
I nomi sono la documentazione più economica che scriverai mai e la più costosa da sbagliare. Java dispone di un insieme forte e quasi universale di convenzioni di denominazione — codificate nell'originale Java Language Specification e rafforzate dal JDK, da ogni libreria principale e da strumenti come Checkstyle. Seguirle non è una questione di gusti: permette a qualsiasi lettore Java di dedurre cosa sia una cosa dal modo in cui è scritta, prima ancora di leggere una singola riga del suo corpo. Questo capitolo raccoglie le regole di denominazione più importanti e le mostra in azione; per spaziatura, posizionamento delle parentesi graffe e layout dei file, consulta le convenzioni di codifica Java.
Le convenzioni di casing in sintesi
Java assegna uno stile di casing distinto a ogni tipo di identificatore. Il solo casing indica al lettore la categoria:
| Identificatore | Convenzione | Esempio |
|---|---|---|
| Pacchetto | tutto minuscolo, con punti, dominio inverso | com.w3docs.billing |
| Classe / interfaccia / enum / record | PascalCase (UpperCamelCase) sostantivo | OrderLine, HttpClient |
| Metodo | camelCase frase verbale | calculateGrossTotal, isBulk |
| Variabile / parametro / campo | camelCase sostantivo | taxRate, orderLines |
Costante (static final) | UPPER_SNAKE_CASE | MAX_RETRY_COUNT |
| Parametro di tipo | singola lettera maiuscola | E, T, K, V |
package com.w3docs.billing; // lowercase, reverse-domain
public class InvoiceService { // PascalCase class
private static final int MAX_RETRY_COUNT = 3; // UPPER_SNAKE_CASE constant
private final TaxTable taxTable; // camelCase field
public BigDecimal calculateTotal(List<LineItem> lineItems) { ... } // camelCase method
}Pacchetti: minuscolo e dominio inverso
I nomi dei pacchetti sono sempre in minuscolo, senza underscore, e iniziano da un dominio che controlli invertito — com.w3docs.billing, non Billing o w3docs_billing. Il prefisso a dominio inverso mantiene i tuoi pacchetti globalmente unici, in modo che non collidano mai con una libreria di terze parti nel classpath. Evita le parole chiave Java e le cifre come primo carattere di qualsiasi segmento. Consulta la sezione creazione di pacchetti per il layout delle directory che questi nomi implicano.
package com.w3docs.billing.tax; // good: lowercase, reverse-domain, dotted
// package Com.W3docs.Billing; // bad: uppercase segments
// package com.w3docs.2024billing;// bad: segment starts with a digitLe classi sono sostantivi, i metodi sono verbi
Una classe, interfaccia, enum o record modella una cosa, quindi il suo nome è un sostantivo in PascalCase: Order, PaymentGateway, OrderLine. Un metodo fa qualcosa, quindi il suo nome è una frase verbale in camelCase: calculateTotal, sendInvoice, parseDate. Ne derivano due sottoconvenzioni importanti:
- I metodi che restituiscono un
booleansi leggono come una domanda:isEmpty,hasNext,canRetry. - Gli accessor classici usano il prefisso
get/set(getName,setName) — ma i record Java generano accessor chiamati come il campo senza prefisso (name(), nongetName()).
interface PaymentGateway { // noun, PascalCase
boolean isAvailable(); // boolean → question form
Receipt charge(Money amount); // verb phrase
}
record Customer(String name, String email) { } // accessors: name(), email()Costanti, variabili e parametri di tipo
Una costante static final il cui valore è fisso a tempo di compilazione usa UPPER_SNAKE_CASE per distinguersi dalle variabili ordinarie: MAX_RETRY_COUNT, DEFAULT_TAX_RATE. Le variabili locali, i parametri e i campi sono sostantivi in camelCase che descrivono il valore, non il suo tipo — preferisci taxRate rispetto a d o theDouble. I parametri di tipo generici sono singole lettere maiuscole per consolidata convenzione:
| Lettera | Significato convenzionale |
|---|---|
E | Element (in una collection) |
T | Type (un tipo generico) |
K, V | Key e Value (in una map) |
R | Return type |
N | Number |
static final double DEFAULT_TAX_RATE = 0.20; // constant
public <K, V> Map<K, V> copyOf(Map<K, V> source) { ... } // type params K, VEvita questi errori comuni
Alcuni anti-pattern ricorrono continuamente. Compilano, ma ostacolano il lettore:
- Nomi con notazione ungherese / codifica del tipo —
strName,iCount,lstOrders. Il tipo è già nella dichiarazione; il nome dovrebbe descrivere il significato. - Variabili locali con una sola lettera oltre ai contatori di ciclo —
c,x,tmpper un valore di dominio nascondono l'intento. - Abbreviazioni criptiche —
calcGrsTtl. Scrivi le parole per esteso; i moderni IDE completano automaticamente. l(L minuscola) eOcome nomi di variabili — sono visivamente indistinguibili da1e0.- Nomi di classe che sono verbi (
ProcessData) o nomi di metodo che sono sostantivi — preferisciorder.calculateTotal()per qualcosa che calcola, riservando la forma sostantivale pura agli accessor.
Un esempio pratico: le convenzioni in un unico programma
Questo programma applica ogni regola descritta sopra in un unico file — una costante, un record con accessor senza prefisso, un metodo booleano a forma di domanda, un metodo camelCase con parametri descrittivi e una lista generica. Leggi il codice sorgente e l'output insieme per vedere come il casing si mappa sulla categoria.
Cosa trarre dall'esecuzione:
- Le due costanti
UPPER_SNAKE_CASEstampanomax retry count : 3edefault tax rate: 0.2— il loro casing segnala nel punto di utilizzo che si tratta di valori fissi e condivisi, non di variabili locali riassegnabili. OrderLineè un record in PascalCase, e il ciclo legge i suoi dati tramiteproductName(),quantity()elineTotal()— nota che non c'è il prefissoget, perché gli accessor dei record sono chiamati esattamente come il componente.isBulk()stampabulk=trueper la riga da 12 unità ebulk=falseper quella da 1 unità: il prefissoisindicava che restituiva un boolean prima ancora di leggerne il corpo, e l'output conferma che la convenzione paga al sito di chiamata.calculateGrossTotalè un metodo con frase verbale i cui parametriorderLinesetaxRatedescrivono il significato, non il tipo — il risultatogross total : 111.60(93.00 netto per 1.20) è esattamente ciò che il nome del metodo prometteva.- L'ultima riga usa
List<String>, un tipo generico parametrizzato con un tipo concreto, che richiama la convenzione dei parametri di tipo (Eper elemento) con cui le collection JDK sono dichiarate — il programma stampa[alpha, beta]per mostrare la lista tipizzata in azione.