Un miembro static pertenece a la clase y se comparte entre sus instancias.
Hasta ahora, cada vez que creábamos un objeto (una instancia), este tenía su propia copia de los datos.
Si creamos 100 objetos Robot, tenemos 100 variables nivelBateria en la memoria. Y es lógico, porque si el robot 1 gasta batería, no queremos que el robot 2 se apague.
Pero, ¿qué pasa si queremos compartir un dato entre TODOS los objetos?
Por ejemplo, queremos saber el número total de robots fabricados. O queremos una constante universal como la gravedad (9.8). No tiene sentido copiar el valor 9.8 dentro de cada uno de los 1.000 objetos creados. Sería un desperdicio de memoria absurdo.
Para esto existe el modificador static.
¿Qué significa static?
Cuando marcamos un atributo o un método como static, deja de pertenecer al objeto (a la instancia) y pasa a pertenecer a la Clase (al plano).
Variables estáticas (atributos de clase)
Son variables asociadas a la clase y compartidas por sus instancias. Hay un valor por clase cargada, un matiz relevante cuando intervienen varios class loaders.
El ejemplo clásico: Un contador de instancias.
public class Robot {
// Variable de instancia (Cada robot tiene su nombre)
private String nombre;
// Variable ESTÁTICA (Compartida por todos los robots)
// Sirve para contar cuántos hemos creado
public static int contadorRobots = 0;
public Robot(String nombre) {
this.nombre = nombre;
// Cada vez que nace un robot, aumentamos el contador compartido
contadorRobots++;
}
}
Cómo acceder a los estáticos
Como pertenecen a la clase, no hace falta tener un objeto para usarlos. Se accede a través del Nombre de la Clase.
// Aún no hay robots, pero la variable ya existe
System.out.println(Robot.contadorRobots); // 0
Robot r1 = new Robot("Wall-E");
Robot r2 = new Robot("R2-D2");
// Accedemos a la variable compartida
System.out.println(Robot.contadorRobots); // 2
// OJO: También se puede acceder desde el objeto, pero es MALA PRÁCTICA
// System.out.println(r1.contadorRobots); // Funciona, pero confunde.
Constantes (static final)
Si combinamos static con final, obtenemos una referencia o valor que solo puede asignarse una vez. Si apunta a un objeto mutable, final no vuelve inmutable ese objeto.
En Java, las constantes se escriben por convención en MAYÚSCULAS_CON_GUIONES_BAJOS (Screaming Snake Case).
public class Fisicas {
// Constante pública y global
public static final double GRAVEDAD = 9.81;
public static final double PI = 3.1415926535;
}
Uso:
double fuerza = masa * Fisicas.GRAVEDAD;
// Fisicas.GRAVEDAD = 10.0; // ¡ERROR! Es final, no se puede tocar.
La clase Math de Java está llena de constantes así, como Math.PI o Math.E.
Métodos estáticos (utility methods)
Un método estático es una función que no necesita un objeto para funcionar. No depende del estado interno (variables) de ninguna instancia concreta.
Son métodos “herramienta” o de utilidad.
- Ejemplo:
Math.sqrt(25). No necesitas crear un objetoMath(new Math()) para calcular una raíz cuadrada. Simplemente usas la herramienta.
public class Calculadora {
// Método estático: Recibe todo lo que necesita por parámetros
public static int sumar(int a, int b) {
return a + b;
}
}
// Uso:
int resultado = Calculadora.sumar(5, 5);
La restricción de oro
Un método estático NO puede usar this.
¿Por qué? Porque this hace referencia al “objeto actual”, y un método estático se puede ejecutar sin que exista ningún objeto.
public class Robot {
private String nombre; // Instancia
public static void info() {
// System.out.println(this.nombre); // ¡ERROR FATAL!
// El método estático no sabe de qué robot hablas.
// No tiene acceso a variables de instancia.
System.out.println("Soy la clase Robot."); // Esto sí vale
}
}
¿Por qué el main es static?
Ahora cobra sentido la famosa línea:
public static void main(String[] args)
Es static porque, cuando arrancas el programa, aún no existe ningún objeto. La JVM necesita un punto de entrada que pueda llamar “desde la nada”, sin tener que hacer new Programa().
Cuándo usar estáticos
- Contadores globales.
- Constantes (
Math.PI). - Métodos de utilidad puros (
Math.max, conversores de unidades). - El método
main.
Y no ls uses, para todo lo demas 😊.