Modificadores de acceso en Java
Controla la visibilidad en Java con los modificadores de acceso public, private, protected y package-private (predeterminado).
Los modificadores de acceso determinan quién puede ver y usar una clase, campo, método o constructor. Java tiene cuatro niveles — public, protected, package-private (sin palabra clave) y private — que van desde "cualquier parte del mundo" hasta "solo esta clase". Elegir el correcto es la forma de trazar un límite entre la interfaz de un objeto y sus detalles internos.
Los cuatro niveles
De mayor a menor permisividad:
| Modificador | Visible desde |
|---|---|
public | En cualquier lugar |
protected | El mismo paquete, o cualquier subclase (incluso en otro paquete) |
| (sin palabra clave) | Solo el mismo paquete — package-private |
private | Solo la misma clase |
Eso es todo. No existe "friend" ni "module-internal" en este nivel; la visibilidad de módulos es una característica separada del Java Platform Module System que rara vez necesitarás.
public
Un miembro public forma parte de la API publicada de la clase — visible para cualquier código que pueda ver la clase en sí:
public class Greeter {
public String greet(String name) {
return "Hello, " + name;
}
}
new Greeter().greet("world"); // anyone can call thisUsa public para las cosas que quieres que otro código — incluso otros proyectos — pueda llamar. El costo es que una vez que algo es público, te has comprometido con ello; cambiar la firma rompe cada llamador.
private
private restringe un miembro a su clase declarante. Nada externo puede tocarlo — ni siquiera una subclase:
public class Account {
private int balance; // only Account can read/write
public void deposit(int amount) {
if (amount <= 0) throw new IllegalArgumentException();
balance += amount; // ok — same class
}
}
Account a = new Account();
a.balance = -1; // ERROR — balance is privateEste es el elemento fundamental para los campos. Ocultar el estado detrás de private es lo que hace que la validación en deposit tenga sentido real. El capítulo de encapsulación profundiza en el patrón.
Package-private (sin palabra clave)
Si omites el modificador por completo, el miembro es visible para todo lo que esté en el mismo paquete — pero no para nada fuera de él:
// in package com.shop
class CartHelper { // no public — package-private
static int sum(int[] prices) { ... }
}Otras clases en com.shop pueden llamar a CartHelper.sum(...); el código en com.app ni siquiera puede ver que la clase existe. Úsalo para auxiliares internos que el paquete necesita compartir pero que no forman parte de la API externa del proyecto.
Un error común: olvidar el modificador y sorprenderse cuando la clase puede usarse desde main (también en el mismo paquete mientras aprendes) pero no desde una prueba en un paquete diferente.
protected
protected es package-private más subclases. El código en el mismo paquete puede usar el miembro, y cualquier subclase — incluso en un paquete diferente — también puede usarlo:
public class Shape {
protected double area; // subclasses can read/write
}
public class Circle extends Shape {
Circle(double r) {
this.area = Math.PI * r * r; // ok — subclass access
}
}Este es el modificador que debes usar cuando quieres que las subclases puedan conectarse a la maquinaria del padre, pero no quieres que el código cliente general lo toque. En la práctica, protected aparece con mucha menos frecuencia que public o private; muchos diseñadores prefieren campos private con métodos de acceso protected para el mismo efecto con más control.
Dónde se aplican los modificadores
Puedes colocar un modificador en:
- Una clase en sí misma (
public class Foo). Las clases de nivel superior solo pueden serpublico package-private. Las clases internas pueden ser cualquiera de los cuatro. - Un campo (
private int count). - Un método (
public int get() {...}). - Un constructor (
private Singleton() {...}— ver patrón singleton).
No puedes colocar un modificador de acceso en una variable local ni en un parámetro de método. Estos tienen un alcance determinado únicamente por el lugar donde se declaran.
La regla "una clase pública por archivo"
Un archivo .java puede declarar varias clases de nivel superior, pero como máximo una de ellas puede ser public, y el nombre de esa clase debe coincidir con el nombre del archivo:
// file: Order.java
public class Order { ... } // ok — matches filename
class OrderHelper { ... } // ok — package-private
public class Customer { ... } // ERROR — second public classLa mayoría de los proyectos mantienen una clase por archivo de todas formas, pero los auxiliares package-private junto a una clase pública a veces son útiles.
Elegir el correcto
Una regla general que escala bien:
- Por defecto, usa
privatepara campos y métodos auxiliares. publicpara los métodos que realmente quieres que se llamen desde fuera.- Package-private para las cosas que necesitan compartirse dentro de un paquete pero no exponerse más allá.
protectedsolo cuando específicamente quieres acceso de subclase también.
Es fácil ampliar el acceso más tarde (private → public); es doloroso restringirlo sin romper a los llamadores. Empieza de forma restrictiva.
Los modificadores no cambian el comportamiento
Un modificador de acceso es una comprobación en tiempo de compilación. En tiempo de ejecución, dos campos int iguales se comportan de manera idéntica sin importar si fueron declarados public o private. El modificador existe únicamente para impedir que otro código compile contra el miembro — para hacer cumplir un límite que estás declarando.
Un ejemplo práctico
Qué sigue
public, protected, private son modificadores de acceso. Java tiene otra familia — los modificadores sin acceso como static, final, abstract, synchronized — que controlan el comportamiento en lugar de la visibilidad. El siguiente capítulo, modificadores sin acceso, es un recorrido por ellos.