Static

En Java tenemos dos tipos de miembros en una clase:


1. Miembros de instancia 👤

  • Pertenecen a cada objeto que creamos.

  • Cada objeto tiene su propia copia de esos valores.

Ejemplo:

public class Empleado {
    private int salarioBase;   // miembro de instancia
}

Si haces:

Empleado e1 = new Empleado(1000, 20);
Empleado e2 = new Empleado(2000, 30);

👉 e1 tiene un salario base distinto de e2.


2. Miembros estáticos (static) 🌍

  • No pertenecen a un objeto, sino a la clase en sí.

  • Se comparten entre todos los objetos.

  • Se crean una sola vez en memoria.

Ejemplo:

public class Empleado {
    public static int numberOfEmployees; // miembro estático
}

Si haces:

Empleado e1 = new Empleado(1000, 20);
Empleado e2 = new Empleado(2000, 30);

System.out.println(Empleado.numberOfEmployees);

👉 Aunque tengas 2 empleados, numberOfEmployees es uno solo y vale 2, compartido entre todos.


🔑 Metáfora

  • Imagina una fábrica 🏭.

  • Cada empleado tiene su propia tarjeta de identificación (miembro de instancia).

  • Pero toda la fábrica tiene un único reloj de entrada en la pared (miembro estático).

  • No importa cuántos empleados entren, el reloj es uno solo y lo ven todos.


⚡ Cosas importantes de static

  1. Los atributos estáticos se acceden así:

    Empleado.numberOfEmployees;

    No necesitas crear un objeto.

  2. Los métodos estáticos solo pueden usar otros miembros estáticos.

    (Porque no dependen de un objeto).

  3. Ejemplo clásico en Java que ya usaste:

    public static void main(String[] args) { ... }

    El main es static porque el programa necesita ejecutarlo sin crear primero un objeto.

Ejemplo con campo estático

public class Empleado {
    private int salarioBase;
    private int tasaHoraria;

    // Campo estático (compartido por todos)
    public static int numberOfEmployees;

    public Empleado(int salarioBase, int tasaHoraria) {
        setSalarioBase(salarioBase);
        setTasaHoraria(tasaHoraria);
        numberOfEmployees++;  // cada vez que nace un objeto, aumentamos
    }

    public int calcularSalarioBase(int horaExtra) {
        return salarioBase + (tasaHoraria * horaExtra);
    }

    public int calcularSalarioBase() {
        return calcularSalarioBase(0);
    }

    // Métodos privados de validación
    private void setSalarioBase(int salarioBase) {
        if (salarioBase <= 0)
            throw new IllegalArgumentException("Salario no puede ser <= 0");
        this.salarioBase = salarioBase;
    }

    private void setTasaHoraria(int tasaHoraria) {
        if (tasaHoraria < 0)
            throw new IllegalArgumentException("La tarifa por hora no puede ser negativa");
        this.tasaHoraria = tasaHoraria;
    }

    // 🔹 Método estático → pertenece a la clase
    public static void printNumberOfEmployees() {
        System.out.println("Número de empleados: " + numberOfEmployees);
    }
}

Uso en el main

public class Main {
    public static void main(String[] args) {
        var e1 = new Empleado(10_000, 20);
        var e2 = new Empleado(15_000, 25);

        // Llamamos a método estático directamente desde la clase
        Empleado.printNumberOfEmployees();

        // Uso de métodos de instancia
        System.out.println("Salario e1: " + e1.calcularSalarioBase(5));
        System.out.println("Salario e2: " + e2.calcularSalarioBase());
    }
}

Resultado en consola

Número de empleados: 2
Salario e1: 10100
Salario e2: 15000
  • static → pertenece a la clase, no a cada objeto.
  • Accedemos con Empleado.printNumberOfEmployees(), no con e1.printNumberOfEmployees().
  • Se usa cuando un valor o acción es común a todos los objetos (ej: contar cuántos empleados se han creado).
  • Los métodos estáticos no pueden usar métodos de instancia directamente (porque no dependen de un objeto).