W3docs

Palavra-chave static em Java

Declare membros de nível de classe em Java com static — campos, métodos, blocos e classes aninhadas estáticas.

static é a palavra-chave que eleva um membro de classe de "um por instância" para "um por classe". Um campo estático possui uma única cópia compartilhada por todos os objetos. Um método estático pertence à própria classe e executa sem nenhuma instância. Um bloco estático é executado uma vez, quando a classe é carregada pela primeira vez. Uma classe aninhada estática vive dentro de outra classe sem precisar de um objeto envolvente.

A regra geral: membros static não têm this. Todo o restante do comportamento decorre disso.

Campos estáticos

Um campo estático é declarado com static no corpo da classe. Há exatamente uma cópia, independentemente de quantas instâncias existam:

public class Counter {
  static int total;       // one Counter.total for everybody
  int count;              // each Counter has its own count
}

Counter a = new Counter();   a.count++;   Counter.total++;
Counter b = new Counter();   b.count++;   Counter.total++;

System.out.println(a.count);          // 1
System.out.println(b.count);          // 1
System.out.println(Counter.total);    // 2

Acesse um campo estático pelo nome da classe (Counter.total) — essa é a forma canônica. O Java também permite escrever a.total porque a é um Counter, mas todo linter do mundo sinaliza esse estilo.

Métodos estáticos

Um método estático pertence à classe. Chame-o com NomeDaClasse.metodo(...):

public class MathUtil {
  public static int square(int n) {
    return n * n;
  }
}

int x = MathUtil.square(7);     // 49

Dentro de um método estático, não há this — você não pode ler campos de instância nem chamar métodos de instância sem qualificação, pois não há instância atual a partir da qual lê-los:

public class Counter {
  int count;
  static void reset() {
    count = 0;      // ERROR: cannot reference instance field from static context
  }
}

Você ainda pode receber uma instância como parâmetro e operar sobre ela:

static void resetThis(Counter c) {
  c.count = 0;     // ok — c is a parameter, not this
}

A direção inversa funciona bem: um método de instância pode chamar um método estático sem cerimônia, pois a classe está sempre disponível mesmo quando uma instância existe.

Quando escolher static

O único teste é verificar se o membro depende de estado por instância.

Depende de this?Usar
Não — cálculo puro, contador compartilhado, método fábricastatic
Sim — lê ou grava os próprios campos do objetoinstância
public static int hoursToSeconds(int h) { return h * 3600; }   // no this needed → static
public        int rentalDays()           { return days; }       // reads this.days → instance

Um cheiro comum: um método de instância que ignora this. Ele está mentindo sobre ser específico da instância — torne-o static e o chamador não precisará mais inventar um objeto apenas para usá-lo.

Constantes estáticas

A combinação static final é a forma padrão para constantes:

public static final double TAX_RATE = 0.08;
public static final int    MAX_RETRIES = 3;
public static final String DEFAULT_LOCALE = "en";

Por convenção, constantes são nomeadas em UPPER_SNAKE_CASE. Elas são incorporadas em tempo de compilação quando o valor é primitivo ou um literal String, o que as torna tão rápidas quanto um literal no ponto de chamada.

Blocos estáticos

Um bloco static { ... } é executado uma vez, quando a classe é carregada na JVM pela primeira vez. Use-o para a configuração única de campos estáticos que precisam de mais do que uma única expressão:

public class Lookup {
  static final Map<String, Integer> WEEKDAYS = new HashMap<>();
  static {
    WEEKDAYS.put("Mon", 1);
    WEEKDAYS.put("Tue", 2);
    WEEKDAYS.put("Wed", 3);
    WEEKDAYS.put("Thu", 4);
    WEEKDAYS.put("Fri", 5);
    WEEKDAYS.put("Sat", 6);
    WEEKDAYS.put("Sun", 7);
  }
}

Blocos estáticos são poderosos, mas fáceis de usar em excesso. Prefira um inicializador de campo simples quando uma expressão for suficiente.

Campos estáticos e blocos estáticos são executados de cima para baixo na ordem em que aparecem no código-fonte. Se um inicializador acessar um campo (por meio de um método) antes da própria linha desse campo ter sido executada, ele verá o valor padrão (0, false ou null) — portanto, a ordem importa:

public class Order {
  static int a = compute();          // runs first; b is still 0 → a becomes 1
  static int b = 10;                 // runs second
  static int compute() { return b + 1; }
}
// Order.a == 1, Order.b == 10

(Ler b diretamente nessa primeira linha — static int a = b + 1; — seria um erro de compilação "referência direta ilegal"; somente o caminho indireto por meio de um método expõe o valor padrão.)

Classes aninhadas estáticas

Uma classe declarada static dentro de outra classe é uma classe aninhada estática. Ao contrário de uma classe interna não estática, ela não carrega uma referência implícita a uma instância da classe externa:

public class Outer {
  static class Inner {           // does not need an Outer instance
    void hello() { System.out.println("hi"); }
  }
}

Outer.Inner i = new Outer.Inner();   // create directly
i.hello();

É assim que temos encapsulado classes auxiliares no mesmo arquivo que main em blocos static class Foo {...} anteriores — main é estático, portanto precisamos que o auxiliar também seja estático para instanciá-lo sem uma instância Outer envolvente. O capítulo de classes aninhadas cobre todos os quatro tipos.

static não é "o construtor"

Iniciantes às vezes confundem "static = executa uma vez" com "static = executa na criação do objeto". A inicialização estática acontece uma vez por classe, não uma vez por objeto. O construtor executa uma vez por objeto. São mecanismos distintos e disparam em situações diferentes.

Membros estáticos em interfaces

Interfaces também podem ter métodos static. Eles se comportam da mesma forma que estáticos de classe — chame-os com NomeDaInterface.metodo(...):

public interface Path {
  static Path of(String s) { return new SimplePath(s); }
}

Path p = Path.of("/tmp/foo");

O capítulo de interfaces cobre quando isso é uma boa ideia (métodos fábrica na própria interface).

Um exemplo prático

java— editable, runs on the server

Este programa imprime:

#1  apple   base=0.50 USD,  with tax=0.54
#2  bread   base=2.40 USD,  with tax=2.59
#3  butter  base=3.10 USD,  with tax=3.35
Total items ever created: 3

Observe como o exemplo mistura todos os quatro tipos: as constantes e a tabela de pesquisa são preenchidas antes de qualquer Item existir, cada Item mantém seus próprios name e basePrice, e o campo compartilhado único itemsCreated distribui o id sequencial.

O que vem a seguir

static permite dizer quem possui um membro. O próximo complemento é final, que permite dizer se ele pode mudar. Juntos, static final é a forma padrão para constantes; por si só, final molda herança e design imutável. Continue em java-final.

Prática

Prática
Por que um método estático recebe um erro de compilação ao tentar ler um campo de instância pelo seu nome simples?
Por que um método estático recebe um erro de compilação ao tentar ler um campo de instância pelo seu nome simples?
Was this page helpful?