Control de visibilidad

public, private, protected, package-private y paquetes

Los cuatro niveles de acceso

Java tiene cuatro niveles de acceso. El predeterminado (sin modificador) es package-private — visible solo dentro del mismo paquete. Es el nivel más olvidado y a menudo el más útil para clases de implementación internas.

public class EjemploVisibilidad {
    public    String publico;     // accesible desde cualquier lugar
    protected String protegido;   // accesible desde el mismo paquete y subclases
              String packagePriv; // package-private: solo el mismo paquete (sin modificador)
    private   String privado;     // solo dentro de esta clase
}
// Resumen de acceso por contexto:
//
// Modificador    | Misma clase | Mismo paquete | Subclase | Resto
// ---------------|-------------|---------------|----------|-------
// public         |     ✓       |      ✓        |    ✓     |   ✓
// protected      |     ✓       |      ✓        |    ✓     |   ✗
// (sin modif.)   |     ✓       |      ✓        |    ✗     |   ✗
// private        |     ✓       |      ✗        |    ✗     |   ✗

El sistema de paquetes

Los paquetes organizan el código y son la unidad de visibilidad package-private. Un paquete es un namespace: com.empresa.servicio y com.empresa.repositorio son paquetes distintos aunque compartan prefijo. La estructura de directorios debe coincidir exactamente con la declaración package.

// Los paquetes son la unidad de visibilidad en Java
// Estructura de directorios = estructura de paquetes

// src/com/empresa/servicio/UsuarioService.java
package com.empresa.servicio;

import com.empresa.modelo.Usuario;     // import explícito
import com.empresa.repositorio.*;      // import comodín (evitar en producción)

public class UsuarioService {
    // ...
}

protected: el nivel más malinterpretado

protected permite acceso a subclases en cualquier paquete, además de todo el paquete actual. Se usa habitualmente en clases base de frameworks (plantillas, repositorios) para exponer operaciones a subclases sin hacerlas públicas.

// protected: accesible en subclases aunque estén en otro paquete
package com.empresa.base;
public class Repositorio {
    protected Connection obtenerConexion() { // accesible por subclases
        return DataSource.getConnection();
    }
}

// --- en otro paquete ---
package com.empresa.impl;
import com.empresa.base.Repositorio;

public class UsuarioRepositorio extends Repositorio {
    public Usuario buscar(Long id) {
        Connection con = obtenerConexion(); // OK: es subclase
        // ...
    }
}

Regla de mínima exposición

El principio general es usar siempre el modificador más restrictivo que permita al código funcionar. Cuanto más se expone, más difícil es cambiar la implementación sin romper el código que depende de ella.

// Regla general: usar el modificador más restrictivo posible

public class Pedido {
    private Long id;                      // nunca exponer estado mutable directamente
    private List<LineaPedido> lineas;
    private EstadoPedido estado;

    // Constructor: único punto de creación válida
    public Pedido(Long id) {
        this.id = id;
        this.lineas = new ArrayList<>();
        this.estado = EstadoPedido.BORRADOR;
    }

    // Getter sin setter: id es inmutable una vez creado
    public Long getId() { return id; }

    // Comportamiento como método, no como setter directo
    public void confirmar() {
        if (lineas.isEmpty()) throw new IllegalStateException("Pedido vacío");
        estado = EstadoPedido.CONFIRMADO;
    }

    // Vista defensiva: no exponer la lista interna directamente
    public List<LineaPedido> getLineas() {
        return Collections.unmodifiableList(lineas);
    }
}
Effective Java, ítem 15: minimiza la accesibilidad de clases y miembros. Una API pública es un contrato para siempre — lo que hoy es public es difícil de quitar mañana sin romper compatibilidad. Package-private es la opción predeterminada correcta para clases de implementación.

Siguiente apartado → Clases internas, envolventes y estáticas

Índice de la sección

Índice del curso