Menu

Modificadores de acceso en Java: public, private, protected, default

Cómo los cuatro niveles de acceso de Java - public, private, protected y package-private - controlan qué puede ver y tocar el resto del código.

Esta página incluye editores ejecutables: edita, ejecuta y ve el resultado al instante.

Quién puede tocar tu código

Un modificador de acceso es una palabra clave delante de una clase, campo, método o constructor que decide quién más tiene permiso para usarlo. Es la base del encapsulamiento: ocultas las entrañas desordenadas de una clase y expones solo las partes que confías que otro código llame.

Java tiene cuatro niveles, del más abierto al más cerrado: public, protected, default (sin palabra clave en absoluto) y private. Acierta con ellos y una clase se vuelve segura de modificar después, porque nada externo depende de detalles que nunca prometiste mantener.

private: visible solo dentro de la clase

private es el nivel más estricto. Un miembro private solo puede ser tocado por código escrito dentro de la misma clase: ni subclases, ni otras clases del mismo paquete, nadie. Aquí es donde pertenecen la mayoría de tus campos.

balance es private, así que la única forma de cambiarlo es a través de deposit, que rechaza los importes negativos. Si balance fuera public, cualquier código podría escribir account.balance = -9999 y saltarse la comprobación por completo. Esa protección es el sentido entero de ocultar el campo.

Prueba a descomentar account.balance = 500; en main y obtendrás un error de compilación: balance has private access in BankAccount.

public: visible en todas partes

public es el extremo opuesto: cualquiera, en cualquier lugar, puede usar el miembro. Los nombres de tus métodos que otro código está destinado a llamar suelen ser public. También lo es la propia clase cuando necesita ser alcanzable desde otros paquetes.

El patrón habitual - a veces llamado la API pública de una clase - es campos privados, métodos públicos. Los campos guardan estado que nadie más debería tocar; los métodos son las puertas controladas de entrada y salida. getBalance y deposit de arriba son exactamente esto.

default (package-private): sin palabra clave en absoluto

Si no escribes ningún modificador, obtienes acceso default, también llamado package-private. El miembro es visible para todas las clases del mismo paquete e invisible para todo lo de fuera. No hay palabra clave para este nivel: la ausencia de una es el nivel.

class Invoice {       // sin modificador -> visible solo dentro de este paquete
    int amount;       // sin modificador -> campo package-private
}

Esto atrapa a muchos principiantes: omitir public no hace que algo sea private, lo hace package-private. Un campo que querías mantener en secreto sigue siendo totalmente legible y escribible por cualquier clase que resulte vivir en el mismo paquete. Si quieres que esté realmente oculto, debes escribir private explícitamente.

El acceso default es genuinamente útil para clases auxiliares que son un detalle de implementación de un paquete: no las exportas, pero las clases que cooperan dentro del paquete pueden seguir usándolas libremente.

protected: paquete más subclases

protected es un escalón más laxo que default. Un miembro protected es visible en todas partes donde lo es default (el mismo paquete), y también para las subclases, incluso subclases en un paquete diferente. Está diseñado para cosas que quieres compartir con las clases que extienden la tuya, pero no con todo el mundo.

Dog accede a name y sound() porque son protected y Dog es una subclase. El código externo que no es una subclase y no está en el paquete sigue sin poder tocarlos. Recurre a protected cuando estés diseñando una clase pensada para ser extendida; de lo contrario, prefiere private.

Los cuatro niveles de un vistazo

Aquí está el panorama completo, del más restrictivo al más abierto:

ModificadorMisma claseMismo paqueteSubclase (otro paquete)En todas partes
privatenonono
defaultnono
protectedno
public

Una regla práctica sencilla: empieza con private y solo afloja cuando algo realmente necesite un acceso más amplio. Es mucho más fácil ampliar el acceso después que restringirlo una vez que otro código ha empezado a depender de un miembro.

Modificadores en las propias clases

Los modificadores de acceso se aplican también a las clases, no solo a los miembros, pero una clase de nivel superior (una no anidada dentro de otra) solo puede ser public o default. No puedes escribir una clase de nivel superior private o protected.

public class Order { ... }   // alcanzable desde cualquier paquete
class LineItem { ... }       // default - solo este paquete puede verla

Una clase de nivel superior public debe vivir en un archivo con su nombre (Order.java). Las clases anidadas, en cambio, pueden usar los cuatro modificadores, razón por la cual los ejemplos de arriba podían marcar las clases internas como private o default. Un punto sutil: un método public que devuelve un tipo package-private no es muy útil para los llamadores externos, así que mantén tu superficie pública coherente.

Siguiente: miembros estáticos

Hasta ahora cada campo y método aquí pertenece a una instancia: creas un objeto con new y luego llamas a métodos sobre él. Pero a veces un valor o comportamiento pertenece a la clase en su conjunto, compartido entre todas las instancias, como un contador de cuántos objetos existen. Para eso sirve la palabra clave static, y es lo que viene a continuación.

Preguntas frecuentes

¿Cuáles son los cuatro modificadores de acceso en Java?

public, private, protected y el default (sin palabra clave, también llamado package-private). public es visible en todas partes, private solo dentro de la misma clase, protected dentro del paquete más las subclases, y default solo dentro del mismo paquete.

¿Cuál es la diferencia entre public y private en Java?

public significa que cualquier código en cualquier lugar puede acceder al miembro. private significa que solo el código dentro de la misma clase puede hacerlo: ni las subclases ni otras clases pueden siquiera verlo. Normalmente haces los campos private y los expones a través de métodos public.

¿Qué significa que un campo de Java no tenga modificador de acceso?

Sin palabra clave significa acceso default (package-private): el miembro es visible para todas las clases del mismo paquete, pero invisible fuera de él. Es más estricto que public pero más laxo que private, y es fácil omitirlo por accidente, así que sé deliberado al respecto.

Coddy programming languages illustration

Aprende a programar con Coddy

COMENZAR