Modificadores sin acceso en Java
Usa los modificadores sin acceso de Java — static, final, abstract, synchronized, transient, volatile — y lo que controla cada uno.
Los modificadores de acceso de Java — public, protected, private — controlan quién puede ver un miembro. Los modificadores sin acceso controlan cómo se comporta. Son un pequeño conjunto de palabras clave que modifican la propiedad, la mutabilidad, los hilos, la serialización y algunas otras cosas. Este capítulo es el mapa; cada modificador tiene un capítulo o sección más completo en otro lugar.
La lista completa
| Modificador | Se aplica a | Qué hace |
|---|---|---|
static | campos, métodos, clases anidadas, bloques | Pertenece a la clase, no a las instancias |
final | clases, métodos, campos, parámetros, variables locales | No se puede reasignar/sobrescribir/extender |
abstract | clases, métodos | Sin cuerpo / no puede instanciarse; debe ser implementado por una subclase |
synchronized | métodos, bloques | Solo un hilo a la vez puede ejecutarlo sobre un bloqueo dado |
volatile | campos | Las lecturas/escrituras no se almacenan en caché en la memoria local del hilo |
transient | campos | Se omite en la serialización predeterminada |
native | métodos | La implementación reside en código no Java (generalmente C/C++) |
strictfp | clases, métodos | Fuerza el comportamiento estricto de punto flotante IEEE-754 (mayormente histórico) |
default | métodos de interfaz | Proporciona un cuerpo predeterminado en una interfaz |
sealed / non-sealed | clases, interfaces | Restringe qué clases pueden extenderla (Java 17+) |
Usarás static, final, abstract y default constantemente. El resto los verás solo cuando surja su problema específico.
static — pertenece a la clase
Un miembro static está asociado con la clase en sí, no con ninguna instancia individual:
public class Counter {
int instanceCount; // one per Counter object
static int classCount; // one shared by everyone
}static es tan común que tiene su propio capítulo — ver java-static.
final — no puede cambiar
final significa "este enlace está fijo una vez establecido." Se aplica a varias cosas distintas:
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 immutablefinal es la base de las constantes (static final), los objetos inmutables y el diseño seguro de herencia. Tratamiento completo en java-final.
abstract — no tiene cuerpo, debe completarse
abstract aplicado a una clase significa "no puedes instanciar esto directamente — solo las subclases." Aplicado a un método, significa "sin cuerpo aquí — cada subclase concreta debe proporcionar 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() es un error de compilación; new Circle() funciona. Cubierto en clases abstractas.
synchronized — un hilo a la vez
Cuando dos hilos podrían llamar al mismo método en el mismo objeto, marcar el método como synchronized garantiza que solo uno se ejecute a la vez:
public synchronized void deposit(int amount) {
balance += amount;
}Esta es la forma más sencilla de bloqueo. Hay toda una sección de concurrencia más adelante en el libro; por ahora, reconoce que la palabra clave existe y qué hace en términos generales. Ver sincronización para la historia completa.
volatile — visible entre hilos
Sin volatile, los hilos pueden almacenar en caché el valor de un campo. Las lecturas en un hilo podrían nunca ver las escrituras de otro:
private volatile boolean stopped = false;volatile obliga a que cada lectura provenga de la memoria principal y cada escritura vaya a la memoria principal. Es el primo liviano de synchronized para campos de indicador simples — ver volatile para los detalles del modelo de memoria.
transient — omitir en la serialización
La serialización de objetos incorporada de Java (Serializable) escribe todos los campos de forma predeterminada. transient dice "no incluir este" — típicamente usado para cachés, valores calculados o cosas que no tienen sentido fuera del programa en ejecución:
public class Session {
String userId;
transient String passwordHash; // not serialized
}El código moderno usa serializadores JSON más que Serializable, pero la palabra clave sigue siendo útil en bibliotecas que la consideran. Más en serialización.
native — implementado en otro lugar
native es para métodos cuyo cuerpo está en otro lenguaje (C/C++ a través de JNI). Rara vez los escribes tú mismo; solo los ves en bibliotecas de bajo nivel:
public native int currentTimeMillis();strictfp — punto flotante estricto
Originalmente, strictfp forzaba una aritmética de punto flotante IEEE-754 predecible entre plataformas. A partir de Java 17, toda la aritmética de punto flotante es implícitamente estricta, lo que hace que la palabra clave sea un no-op. Puedes ignorarla en su mayoría; persiste en bases de código antiguas.
default — en métodos de interfaz
Dentro de una interfaz, default te permite proporcionar un cuerpo para un método en lugar de dejarlo abstracto:
public interface Greeter {
default String greet(String name) {
return "Hello, " + name;
}
}Sin default, un método de interfaz no tiene cuerpo y cada clase que lo implementa tiene que escribir el suyo. Tratamiento completo en métodos default.
sealed y non-sealed
Una clase sealed nombra la lista exacta de clases permitidas para extenderla. Las subclases deben entonces elegir ser 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 { }Útil para jerarquías de tipos cerradas — ver clases selladas.
Combinar modificadores
Normalmente puedes apilar modificadores libremente, en este orden convencional:
public static final int MAX = 100;
private static volatile int counter;
protected abstract void onInit();Algunas combinaciones son ilegales: un método no puede ser a la vez abstract y final, ni abstract y private, ni abstract y static. El compilador te dirá cuando hayas cruzado una línea.
Un ejemplo práctico
Qué sigue
Los dos próximos capítulos profundizan en los dos modificadores que usarás con más frecuencia: static para los miembros a nivel de clase, y luego final para la inmutabilidad. Léelos en orden.