Saltar a contenido

🧲 Variables, métodos y clases estáticas en Java

Idea clave: static significa “de la clase”, no “del objeto”.

Una clase, método o campo estático se puede usar sin crear objetos de esa clase.
En esta página veremos:


🧱 Variables de instancia vs variables estáticas

🔹 Variables de instancia

Son los atributos normales de un objeto:

  • Pertenecen a cada objeto.
  • Cada objeto tiene su propia copia.
  • Representan el estado de ese objeto.
class Persona {
    private String nombre; // variable de instancia

    public Persona(String nombre) {
        this.nombre = nombre;
    }

    public void printNombre() {
        System.out.println(nombre);
    }
}

public class Main {
    public static void main(String[] args) {
        Persona p1 = new Persona("Patricia");
        Persona p2 = new Persona("Maxi");

        p1.printNombre(); // imprime Patricia
        p2.printNombre(); // imprime Maxi
    }
}

👉 Cada persona tiene su propio nombre.


🔸 Variables estáticas

Son compartidas por todas las instancias de la clase, porque pertenecen a la clase:

  • Se declaran con la palabra reservada static.
  • Solo existe UNA copia en memoria, aunque haya muchos objetos.
  • Todas las instancias ven el mismo valor.
  • Se suelen usar poco: solo cuando de verdad tiene sentido compartir el dato.
public class Contador {
    private static int totalObjetos = 0; // variable estática
    private String nombre;               // variable de instancia

    public Contador(String nombre) {
        this.nombre = nombre;
        totalObjetos++; // cada vez que se crea uno, suma 1
    }

    public void printInfo() {
        System.out.println("Soy " + nombre +
                           " y se han creado " + totalObjetos + " objetos.");
    }
}

public class Main {
    public static void main(String[] args) {
        Contador c1 = new Contador("Primero");
        Contador c2 = new Contador("Segundo");

        c1.printInfo(); // Soy Primero y se han creado 2 objetos.
        c2.printInfo(); // Soy Segundo y se han creado 2 objetos.
    }
}

👉 totalObjetos es de la clase (compartido).
👉 nombre es de cada objeto.


📊 Resumen rápido

Tipo de miembro ¿De quién es? Nº de copias Acceso habitual
Variable de instancia De cada objeto Una por objeto objeto.atributo
Variable estática De la clase Una para toda la clase NombreClase.atributo o desde métodos estáticos

💎 Constantes de clase (static final)

Una constante de clase es un campo:

  • static ➜ es de la clase, hay una sola copia.
  • final ➜ no se puede cambiar su valor (constante).
public class Juego {
    public static final int MODO_UN_JUGADOR = 1;
    public static final int MODO_MULTIJUGADOR = 2;

    private int modo;

    public Juego(int modo) {
        this.modo = modo;
    }

    public static void main(String[] args) {
        Juego juego = new Juego(Juego.MODO_MULTIJUGADOR);
    }
}

✅ Ventajas:

  • Ahorra memoria: solo hay una copia de la constante.
  • Se puede usar sin crear objetos.
  • Hace el código más legible (MODO_MULTIJUGADOR es más claro que 2).

⚙️ Métodos estáticos

Un método estático:

  • Se declara con static.
  • No puede acceder directamente a atributos ni métodos de instancia.
  • Se puede llamar con NombreClase.metodo() o directamente metodo() si está en la misma clase.
  • Se suele usar para:
  • Funciones auxiliares / utilidades
  • Cálculos que no dependen del estado de ningún objeto.
  • El famoso main.
class Calculadora {
    public static int sumar(int a, int b) {
        return a + b;
    }
}

public class Main {
    public static void main(String[] args) {
        int resultado = Calculadora.sumar(5, 6);
        System.out.println(resultado); // 11
    }
}

🚫 Dentro de un método estático:

  • No puedes usar this.
  • No puedes acceder directamente a variables de instancia.
class Ejemplo {
    private int numero = 10;

    public static void metodoEstatico() {
        // System.out.println(numero); // ❌ ERROR: numero es de instancia
    }
}

🧍‍♀️ Métodos de instancia

  • Necesitan un objeto para usarse.
  • Pueden acceder tanto a:
  • Variables y métodos de instancia
  • Como a variables y métodos estáticos
class Cuenta {
    private double saldo;
    private static double interesAnual = 0.02;

    public Cuenta(double saldoInicial) {
        this.saldo = saldoInicial;
    }

    public void aplicarInteres() {         // método de instancia
        saldo += saldo * interesAnual;     // usa saldo (instancia) e interesAnual (estático)
    }

    public static void cambiarInteres(double nuevoInteres) { // método estático
        interesAnual = nuevoInteres;
    }
}

❓ ¿Método estático o de instancia?

Regla práctica:

🔍 Pregunta: “¿Este método necesita datos del objeto (this)?”

  • ➜ Método de instancia.
  • No ➜ Método estático.

Ejemplos típicos de métodos estáticos:

  • Conversión de tipos (parseInt, etc.).
  • Funciones matemáticas (Math.sqrt, Math.random…).
  • Utilidades que no dependen del estado (Collections.sort, etc.).

🧱 Clases internas estáticas

Java no permite que una clase “normal” externa sea estática, pero permite que una clase interna lo sea.

public class Contenedor {

    static int valorEstatico = 42;
    int valorInstancia = 7;

    public static class Interna {
        public static void imprimir() {
            System.out.println(valorEstatico); // ✅ puede acceder a estáticos de Contenedor
            // System.out.println(valorInstancia); // ❌ NO puede acceder a no estáticos
        }
    }

    public static void main(String[] args) {
        Contenedor.Interna.imprimir();
    }
}

📌 Recuerda:

  • Una clase interna estática:
  • No necesita una instancia de la clase externa.
  • Solo puede acceder a miembros estáticos de la clase externa.

⚡ Bloques estáticos de inicialización

Un bloque estático se ejecuta una sola vez, cuando la clase se carga en memoria.

Se usa para inicializar campos estáticos de forma más compleja que con una simple asignación.

public class Configuracion {

    private static String URL_BD;

    static {
        // Este código se ejecuta UNA sola vez, al cargarse la clase
        URL_BD = "jdbc:mysql://localhost:3306/mi_bd";
        System.out.println("Inicializando configuración...");
    }

    public static String getUrlBd() {
        return URL_BD;
    }
}

⚠️ Úsalos con moderación: pueden hacer que el código sea más difícil de seguir.


📦 Imports estáticos

Desde Java 5 se pueden importar miembros estáticos de otras clases:

import static java.lang.Math.PI;
import static java.lang.Math.sqrt;

public class Circulo {
    public static void main(String[] args) {
        double radio = 3;
        double longitud = 2 * PI * radio;     // uso PI sin Math.
        double raiz = sqrt(16);               // uso sqrt sin Math.
    }
}

✅ Útil para:

  • Test unitarios (métodos estáticos de Assertions, Assert, etc.).
  • Código matemático.

⚠️ No abuses: si llenas un archivo de imports estáticos puede perder legibilidad.


🆕 Detalles modernos de Java relacionados con static

Aunque la palabra static existe desde las primeras versiones de Java, hay algunas novedades o matices modernos:

🧪 Métodos estáticos en interfaces (desde Java 8)

Desde Java 8, una interface puede tener métodos estáticos:

public interface Conversor {
    static int aEntero(String valor) {
        return Integer.parseInt(valor);
    }
}

public class Main {
    public static void main(String[] args) {
        int n = Conversor.aEntero("123");
        System.out.println(n);
    }
}

👉 Se llaman con NombreInterfaz.metodoEstatico().
👉 No se heredan como métodos de instancia de las clases que implementan la interfaz.

🔐 Métodos static privados en interfaces (desde Java 9)

También se pueden crear métodos static privados dentro de interfaces para reutilizar código entre otros métodos default o static de la interfaz.

public interface Mensajes {

    static void saludar() {
        imprimir("Hola");
    }

    static void despedir() {
        imprimir("Adiós");
    }

    private static void imprimir(String texto) { // método estático privado
        System.out.println(texto);
    }
}

🚨 Errores típicos con static

  1. Usar static “porque sí”
  2. Poner todo como static para “acceder desde main” es una mala práctica.
  3. Pierdes la gracia de la POO (objetos, estado, encapsulación…).

  4. Acceder a miembros de instancia desde un método estático

  5. Da error de compilación.
  6. Solución: crear un objeto y trabajar con él, o convertir el método en método de instancia.

  7. Usar variables estáticas para guardar estado “global” sin pensar

  8. Puede complicar pruebas, mantenimiento y comportamiento en programas grandes.

  9. Confundir constante de clase con literal mágico

  10. Mejor static final int MAX_INTENTOS = 3; que usar 3 suelto por todas partes.

Recuerda: si un método no necesita acceder a datos del objeto, probablemente debería ser estático 😉