Buenas prácticas de nombres en Java
Reglas prácticas de nomenclatura para paquetes, clases, métodos, variables y constantes en Java.
Los nombres son la documentación más barata que jamás escribirás y la más costosa cuando se hacen mal. Java tiene un conjunto sólido y casi universal de convenciones de nomenclatura — codificadas en la Java Language Specification original y reforzadas por el JDK, todas las bibliotecas principales y herramientas como Checkstyle. Seguirlas no es cuestión de gusto: permite que cualquier lector de Java infiera qué es algo a partir de cómo está escrito, antes de leer una sola línea de su cuerpo. Este capítulo reúne las reglas de nomenclatura más importantes y las muestra en funcionamiento; para espaciado, colocación de llaves y estructura de archivos, consulta las convenciones de código Java.
Las convenciones de mayúsculas de un vistazo
Java asigna un estilo de mayúsculas distinto a cada tipo de identificador. El tipo de mayúsculas solo indica al lector la categoría:
| Identificador | Convención | Ejemplo |
|---|---|---|
| Paquete | todo en minúsculas, con puntos, dominio invertido | com.w3docs.billing |
| Clase / interfaz / enum / record | PascalCase (UpperCamelCase) sustantivo | OrderLine, HttpClient |
| Método | camelCase frase verbal | calculateGrossTotal, isBulk |
| Variable / parámetro / campo | camelCase sustantivo | taxRate, orderLines |
Constante (static final) | UPPER_SNAKE_CASE | MAX_RETRY_COUNT |
| Parámetro de tipo | letra mayúscula única | 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
}Paquetes: minúsculas y dominio invertido
Los nombres de paquetes siempre van en minúsculas, sin guiones bajos, y comienzan con un dominio que controlas escrito al revés — com.w3docs.billing, no Billing ni w3docs_billing. El prefijo de dominio invertido hace que tus paquetes sean globalmente únicos para que nunca colisionen con una biblioteca de terceros en el classpath. Evita palabras reservadas de Java y dígitos como primer carácter de cualquier segmento. Consulta creación de paquetes para ver la estructura de directorios que implican estos nombres.
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 digitLas clases son sustantivos, los métodos son verbos
Una clase, interfaz, enum o record modela una cosa, por lo que su nombre es una frase nominal en PascalCase: Order, PaymentGateway, OrderLine. Un método hace algo, por lo que su nombre es una frase verbal en camelCase: calculateTotal, sendInvoice, parseDate. Se derivan dos subconvenciones importantes:
- Los métodos que devuelven un
booleanse leen como una pregunta:isEmpty,hasNext,canRetry. - Los accesores clásicos usan el prefijo
get/set(getName,setName) — pero los records de Java generan accesores con el nombre del campo sin prefijo (name(), nogetName()).
interface PaymentGateway { // noun, PascalCase
boolean isAvailable(); // boolean → question form
Receipt charge(Money amount); // verb phrase
}
record Customer(String name, String email) { } // accessors: name(), email()Constantes, variables y parámetros de tipo
Una constante static final cuyo valor se fija en tiempo de compilación usa UPPER_SNAKE_CASE para destacarse de las variables ordinarias: MAX_RETRY_COUNT, DEFAULT_TAX_RATE. Las variables locales, parámetros y campos son sustantivos en camelCase que describen el valor, no su tipo — prefiere taxRate sobre d o theDouble. Los parámetros de tipo genérico son letras mayúsculas únicas por convención histórica:
| Letra | Significado convencional |
|---|---|
E | Element (en una colección) |
T | Type (un tipo general) |
K, V | Key y Value (en un mapa) |
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 estos errores comunes
Algunos antipatrones aparecen una y otra vez. Compilan, pero dificultan la lectura:
- Nombres húngaros / con el tipo codificado —
strName,iCount,lstOrders. El tipo ya está en la declaración; el nombre debe describir el significado. - Variables locales de una letra más allá de los contadores de bucle —
c,x,tmppara un valor de dominio ocultan la intención. - Abreviaturas crípticas —
calcGrsTtl. Escribe las palabras completas; los IDEs modernos autocompletán. l(L minúscula) yOcomo nombres de variable — son visualmente indistinguibles de1y0.- Nombres de clase que son verbos (
ProcessData) o nombres de método que son sustantivos — prefiereorder.calculateTotal()para algo que calcula, reservando la forma de sustantivo puro para accesores simples.
Un ejemplo completo: las convenciones en un programa
Este programa aplica cada regla anterior en un único archivo — una constante, un record con accesores sin prefijo, un método de consulta boolean, un método en camelCase con parámetros descriptivos y una lista genérica. Lee el código fuente y la salida juntos para ver cómo el tipo de mayúsculas se corresponde con la categoría.
Qué se puede aprender de la ejecución:
- Las dos constantes
UPPER_SNAKE_CASEse imprimen comomax retry count : 3ydefault tax rate: 0.2— su tipo de mayúsculas señala en el punto de uso que son valores fijos y compartidos, no variables locales que puedas reasignar. OrderLinees un record en PascalCase, y el bucle lee sus datos a través deproductName(),quantity()ylineTotal()— observa que no hay prefijoget, porque los accesores de record reciben el nombre exacto del componente.isBulk()imprimebulk=truepara la línea de 12 unidades ybulk=falsepara la de 1 unidad: el prefijoiste indicó que devolvía un boolean antes de leer su cuerpo, y la salida confirma que la convención da sus frutos en el punto de llamada.calculateGrossTotales un método con frase verbal cuyos parámetrosorderLinesytaxRatedescriben el significado, no el tipo — el resultadogross total : 111.60(93.00 neto por 1.20) es exactamente lo que prometía el nombre del método.- La línea final usa
List<String>, un genérico parametrizado con un tipo concreto, reflejando la convención de parámetros de tipo (Epara elemento) con la que se declaran las colecciones del JDK — el programa imprime[alpha, beta]para mostrar la lista tipada en acción.