W3docs

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:

ModificadorVisible desde
publicEn cualquier lugar
protectedEl mismo paquete, o cualquier subclase (incluso en otro paquete)
(sin palabra clave)Solo el mismo paquete — package-private
privateSolo 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 this

Usa 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 private

Este 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 ser public o 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 class

La 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:

  1. Por defecto, usa private para campos y métodos auxiliares.
  2. public para los métodos que realmente quieres que se llamen desde fuera.
  3. Package-private para las cosas que necesitan compartirse dentro de un paquete pero no exponerse más allá.
  4. protected solo cuando específicamente quieres acceso de subclase también.

Es fácil ampliar el acceso más tarde (privatepublic); 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

java— editable, runs on the server

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.

Práctica

Práctica
Un campo se declara sin ningún modificador de acceso — solo int count;. ¿Quién puede leerlo?
Un campo se declara sin ningún modificador de acceso — solo int count;. ¿Quién puede leerlo?
Was this page helpful?