HOWTO · Java

Clase estática en Java

Este artículo presenta las clases estáticas de Java.

En esta página

Java no permite declarar static una clase de nivel superior. Una clase declarada dentro de otra sí puede ser static; se trata de una clase anidada estática. Puede instanciarse sin crear una instancia de la clase que la contiene y puede usar los miembros estáticos de esta. Si quieres una clase de utilidades que quienes la usan no puedan construir mediante su API pública, usa un constructor privado; es un patrón de diseño distinto.

¿Qué es una clase anidada estática en Java?

Una clase anidada estática es un tipo miembro declarado con la palabra clave static dentro de otra clase. El modificador static significa que las instancias de la clase anidada no tienen una referencia implícita a un objeto de la clase contenedora. No significa que la clase anidada no pueda instanciarse. Se accede a su tipo mediante el nombre de la clase contenedora, como Container.Entry, y sus métodos de instancia se llaman sobre una instancia de ese tipo anidado.

Una clase anidada estática puede acceder a los miembros estáticos de la clase contenedora, incluidos los privados. No puede referirse a los campos o métodos de una instancia contenedora como si tuviera un objeto contenedor. Sí puede hacerlo si se le proporciona explícitamente un objeto de esa clase.

Cómo declarar y usar una clase anidada estática

Declara la clase miembro con static y luego usa el nombre del tipo contenedor para crear una instancia. Este ejemplo completo también muestra cómo acceder a un campo estático de la clase contenedora:

Ejecuta este ejemplo:

El código y las etiquetas o salidas visibles de esta sección se mantienen en inglés.

public class Container {
    private static int count = 3;

    public static class Entry {
        public int value() {
            return count;
        }
    }

    public static void main(String[] args) {
        Container.Entry entry = new Container.Entry();
        System.out.println(entry.value());
    }
}
3

Al ejecutarlo, el ejemplo imprime 3. Si lo adaptas, mantén la clase anidada dentro de la clase contenedora y, fuera de Container, especifica su tipo como Container.Entry. El objeto Entry es una instancia normal, mientras que count pertenece a la propia clase contenedora.

Clase anidada estática frente a clase interna

A una clase miembro no estática se la suele llamar clase interna. Para crear una instancia, se necesita una instancia contenedora: crea un objeto Container y luego usa container.new Inner(). Una instancia de la clase interna puede usar directamente los miembros de instancia del objeto contenedor porque conserva esa asociación.

Una clase anidada estática no tiene esa asociación implícita. Para leer un campo de una instancia contenedora, pasa o consigue de otro modo un objeto Container y accede al campo mediante esa referencia. Ambos tipos de clases anidadas pueden acceder a los miembros que permiten las reglas de acceso de tipos anidados de Java. La diferencia clave es si hay una instancia contenedora disponible automáticamente.

Cómo crear una clase de utilidades que no se pueda instanciar

Una clase de utilidades agrupa operaciones o constantes que no necesitan estado por objeto. Coloca esos miembros en una clase normal de nivel superior, declara como static los miembros adecuados y añade un constructor private para que quienes usan la clase no puedan invocar new desde fuera de ella. Por ejemplo, el patrón es public final class TextTools { private TextTools() {} public static String join(String first, String second) { return first + second; } }; llámalo así: TextTools.join("static ", "utility").

El constructor privado impide la creación normal de instancias desde fuera, pero no convierte TextTools en una clase estática: Java no tiene clases estáticas de nivel superior. Declarar la clase final es opcional y solo impide que se creen subclases. Úsalo cuando esa restricción forme parte del diseño, no como requisito para los métodos de utilidad.

Ideas equivocadas habituales sobre las clases estáticas

Una clase anidada estática se puede instanciar; static elimina el requisito de tener una instancia contenedora implícita. Sus métodos de instancia pueden usar sus propios campos de instancia. El nombre de la clase contenedora califica el tipo anidado, pero para llamar a sus métodos de instancia sigue haciendo falta un objeto de ese tipo.

Un contexto estático no puede acceder a un miembro de instancia de la clase contenedora mediante un nombre sin calificar, porque no hay ningún objeto contenedor disponible automáticamente. Sí puede acceder a ese miembro mediante una referencia explícita a un objeto. Del mismo modo, un constructor privado de una clase de utilidades impide las llamadas normales desde fuera de la clase, pero no hace imposible la construcción en toda circunstancia. Estas distinciones separan la sintaxis de las clases anidadas de Java del patrón de las clases de utilidades.