La directiva static en Java

En este tutorial veremos para qué sirve la directiva static en Java, a qué elementos se puede aplicar, sus características, beneficios y desventajas que pueden tener.

0. Índice de contenidos

1. Introducción

En este tutorial veremos para qué sirve la directiva static en Java, a qué elementos se puede aplicar, sus características, beneficios y desventajas que pueden tener.

Se propondrán una serie de ejemplos y snippets de código para ilustrar cada uno de los puntos mencionados.

2. Entorno

El tutorial está escrito usando el siguiente entorno:

  • MacBook Pro Intel Core 2 Duo 8GB RAM
  • SO: Yosemite
  • IDE: Eclipse Mars 4.5.0
  • Java JDK 1.7

3. ¿Qué es static en Java?

Una clase, método o campo declarado como estático puede ser accedido o invocado sin la necesidad de tener que instanciar un objeto de la clase. Uno de los ejemplos típicos de uso de métodos y variables estáticas es la clase java.lang.Math:

public class MathTest {

    public static void main(String[] args) {
        double floorOfPi = Math.floor(Math.PI);
        System.out.println(floorOfPi);
    }
}

Cuya salida será el suelo matemático del número Pi:

3.0

4. Campos estáticos

Los campos de una clase declarados como estáticos son inicializados en el momento en que se carga la clase en memoria, respetando el orden de declaración. Los campos no estáticos no pueden ser accedidos desde un contexto no estático; este comportamiento resultará en un error en tiempo de compilación.

En conjunción con la directiva final (que evita la modificación del campo), las constantes de clase son definidas de esta manera.

Gracias a que las variables estáticas son compartidas entre todos los objetos de una clase, es posible implementar el patrón Singleton, guardando una referencia de la instancia:

public class SingletonTest {

    private static SingletonTest instance = null;

    protected SingletonTest() {
    }

    public static SingletonTest getInstance() {
        if (instance == null) {
            instance = new SingletonTest();
        }

        return instance;
    }
}

En este caso, el constructor por defecto se oculta con el modificador protected (que podría ser también private) para evitar la instanciación explícita desde fuera del contexto de la clase. Sin embargo, si la construcción es costosa y la clase es poco utilizada, el rendimiento se verá degradado.

Hay que tener en cuenta que, al igual que las variables transient, los campos estáticos no son serializadas. De esta manera, en el proceso de deserialización, los campos estáticos tomarán su valor por defecto (0.0 para los float, null para objetos, etc…).

5. Métodos estáticos

Debido a que los métodos estáticos son enlazados en tiempo de compilación mediante static binding usando la información del tipo, no es posible realizar sobreescritura (override) de métodos.

class Padre {

    public static void metodoEstatico() {
        System.out.println("Invocación desde el padre.");
    }
}

class Hijo extends Padre {

    public static void metodoEstatico() {
        System.out.println("Invocación desde el hijo.");
    }
}

public class BindingTest {

    public static void main(String[] args) {
        Padre p = new Hijo();
        p.metodoEstatico();
        Hijo h = new Hijo();
        h.metodoEstatico();
    }
}
Salida:
Invocación desde el padre.
Invocación desde el hijo.

En la salida podemos comprobar como el método que se invocará vendrá determinado por el tipo desde donde se invoque, aunque los objetos sean del mismo tipo (de la clase Hijo en este caso).

Otra de las consecuencias del static binding es que los métodos estáticos no pueden ser declarados como abstract, por el mismo motivo que la imposibilidad de la sobrecarga de métodos.

Uno de las características que produce más dolores de cabeza al tratar con métodos y variables estáticas es que, debido a su naturaleza, no son seguras para la programación con hilos. Es necesario hacer uso de las directivas synchronized de los métodos y de las variaciones atómicas de los tipos nativos con los campos.

6. Clases y bloques estáticos

Las clases internas pueden ser declaradas estáticas, de tal manera que aumenten la cohesión de la clase que las engloba. Hay que tener en cuenta que, como el resto de clases internas, el compilador crea un fichero .class por cada una de estas clases. Un ejemplo típico de clases internas estáticas son los comparadores de objetos:

public class Objeto {

    private int campo1;
    private String campo2;

    public Objeto(int campo1, String campo2) {
        this.campo1 = campo1;
        this.campo2 = campo2;
    }

    private static class ObjetoComparator implements Comparator<Objeto> {

        @Override
        public int compare(Objeto o1, Objeto o2) {
            return o2.campo1 - o1.campo1;
        }

    }
}

Es posible declarar bloques de código como estáticos, de tal manera que sean ejecutados cuando se cargue la clase. Este tipo de bloques se conocen como bloques de inicialización estáticos (static initializer block). Si no se declara un bloque de este tipo de forma explícita, el compilador Just-in-Time combina todos los campos estáticos en un bloque y los ejecuta durante la carga de clases. Aunque estos bloques no puedan lanzar checked exceptions, las unchecked pueden ocurrir, resultando en un ExceptionInInitializerError.

public class Objeto {

    private static int campo1;

    static {
        campo1 = 10;
    }
}

Los bloques de inicialización pueden ser, además, sustituidos por métodos estáticos:

public class Objeto {

    private static int campo1 = inicializaCampo();

    private static int inicializaCampo() {
        return 10;
    }

}

Como se observa en los ejemplos anteriores, esta funcionalidad permite dotar de cierta lógica la inicialización de variables de clase estáticas sin necesidad de incluirlo en su constructor.

7. Imports estáticos

Una de las características incluidas en Java 5 fué la capacidad de importar los métodos y variables estáticas de un módulo y acceder a ellos como si hubieran sido declarados en la propia clase. Es especialmente útil, y mejora la legibilidad, cuando se están definiendo test unitarios, ya que la mayoría de los métodos de aserción de JUnit son estáticos.

import static org.junit.Assert.assertEquals;

import org.junit.Test;

public class ImportEstático {

    @Test
    public void test() {
        assertEquals(1, 1);
    }

}

8. Conclusiones

La directiva static permite el acceso a métodos y variables de clase sin la necesidad de instanciar un objeto de dicha clase, permitiendo la inicialización de forma cómoda y durante la carga de clase. Además, los import estáticos mejoran la legibilidad de nuestro código, así como las clases estáticas internas la cohesión.

9. Referencias

Comentarios

6 respuestas

  1. Hola!

    En el apartado 4, creo que esta frase está al revés: » Los campos estáticos no pueden ser accedidos desde un contexto no estático; este comportamiento resultará en un error en tiempo de ejecución.»

    Quiero decir, que desde un método no estático, puedo acceder a PI, pero desde un método estático, no puedo acceder a miembros no estátitos, no?

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *

He leído y acepto la política de privacidad

Información básica acerca de la protección de datos

  • Responsable: IZERTIS S.A.
  • Finalidad: Envío información de carácter administrativa, técnica, organizativa y/o comercial sobre los productos y servicios sobre los que se nos consulta.
  • Legitimación: Consentimiento del interesado
  • Destinatarios: Otras empresas del Grupo IZERTIS. Encargados del tratamiento.
  • Derechos: Acceso, rectificación, supresión, cancelación, limitación y portabilidad de los datos.
  • Más información: Puedes ampliar información acerca de la protección de datos en el siguiente enlace:política de privacidad

Estudiante de Grado en Informática en la UAM.

¿Quieres publicar en Adictos al trabajo?

Te puede interesar

30/10/2025

Benjamín Suárez Menéndez

El Complex Problem Solving (CPS) es un proceso estructurado basado en herramientas, técnicas y actitudes que nos facilita la resolución de problemas complejos.

03/10/2025

Miguel García Rodríguez

Descubre cómo el diseño y la psicología del comportamiento utilizan sesgos cognitivos para influir en la toma de decisiones de los usuarios y potenciar la persuasión.

30/09/2025

Iván García Sainz-Aja

En este artículo exploraremos cómo utilizar ZenWave360 para generar un proyecto completo de Spring Boot con Kotlin a partir de un modelo DSL de Lenguaje Ubicuo.