Quando e porquê usar static?
static é uma das palavras-chave do Java, e é também motivo de muita confusão e dúvidas entre o pessoal que esta começando. Aliás, mesmo os mais experienciados confundem-se às vezes em usar ela. O método
static mais famoso de todos é o
main. É através dele que vimos nosso primeiro programa em Java nascer, e é sempre via
main que nossos programas criam vida. Por definição da linguagem Java, o método
main precisa necessariamente ter acesso
public, ser
static, não retornar coisa alguma (
void ) e receber como argumento um array de String (
String args[] ):
public static void main(String args[])
Como regra geral, tenha isso em mente: dentro de métodos
static somente é possível pode acessar outros métodos e variáveis que também sejam
static. Dentro do método pode-se definir qualquer tipo de variável, static ou não. Caso seja necessário acessar algum método ou membro não-static, é necessário criar uma instância da classe e então chamar o que quiser. Já o contrario é um pouco diferente: dentro de membros não-static, é possível acessar tanto propriedades
static quanto as não-static. O fato de ser preciso primeiramente criar uma instância da classe para só então chamar algum método não-static ou acessar uma variável comum dentro de um método
static deve-se ao fato que dentro dele não existe uma referência para o ponteiro
this. O ponteiro
this é utilizado para referenciar propriedades da classe em que estamos trabalhando. Por exemplo:
...
// Variável simples, para guardar o nome
private String nome;
// Algum método comum
public void meuMetodo()
{
this.nome = "Fulano";
}
...
No exemplo acima,
this.nome = "Fulano" diz que estamos atribuindo ao membro da classe chamado
nome o valor "Fulano". O uso de
this é automático, portando o exemplo acima poderia ser escrito simplesmente da forma
...
// Variável simples, para guardar o nome
private String nome;
// Algum método comum
public void meuMetodo()
{
nome = "Fulano";
}
...
Note que agora não mais usamos
this, e funciona da mesma maneira. Se o método
meuMetodo fosse static, o código acima não funcionaria, pois como foi dito antes, métodos
static não possuem
this. Ao contrário do que o nome soa,
static não significa que a variável ou método sera estática do ponto de vista que seu valor não pode mudar (
final é usado para estes casos ).
static nos garante que somente haverá uma, e não mais que uma, referência para determinada variável ou método disponível em mémoria. Em outras palavras, declarando alguma coisa como
static, todas as instâncias da classe irão compartilhar a mesma cópia da variável ou método. Declarar algo como
static também permite você acessar as coisas diretamente, ou seja, sem precisar criar uma instância da classe. Existe inclusive um Design Patter baseado no uso de
static: Singleton.
Para entender melhor tudo o que foi dito, nada melhor que alguns exemplos práticos para ver com os próprios olhos o funcionamento. O primeiro exemplo consiste em uma classe com 2 variáveis, uma static e outra não-static. A cada novo objeto criado, incrementados ambas variáveis e imprimimos o resultado na tela. Digite o seguinte código em um arquivo chamado "TesteStatic.java":
// TesteStatic.java
class Classe1
{
// Variavel static
public static int contador = 0;
// Variavel nao-static
public int outroContador = 0;
public Classe1() {}
// Precisa ser static porque "contador" é static
public static void incrementaContador()
{
contador++;
System.out.println("contador agora é "+ contador);
}
public void incrementaOutroContador()
{
outroContador++;
System.out.println("outroContador agora é "+ outroContador);
}
}
public class TesteStatic
{
public static void main(String args[])
{
Classe1 c1 = new Classe1();
c1.incrementaContador();
c1.incrementaOutroContador();
Classe1 c2 = new Classe1();
c2.incrementaContador();
c2.incrementaOutroContador();
Classe1 c3 = new Classe1();
c3.incrementaContador();
c3.incrementaOutroContador();
Classe1 c4 = new Classe1();
c4.incrementaContador();
c4.incrementaOutroContador();
}
}
A saida gerada por este programa será
- contador agora é 1
- outroContador agora é 1
- contador agora é 2
- outroContador agora é 1
- contador agora é 3
- outroContador agora é 1
- contador agora é 4
- outroContador agora é 1
Note que a variavel "contador", que é
static, não teve seu valor zerado a cada novo objeto criado da classe
Classe1, mas sim incrementado, enquando "outroContador", que é uma variável comum, ficou sempre em 1, pois a zeramos o valor no construtor da classe.
Ao contrário de tipos de dados não-static, qualquer variável ou método
static podem ser acessado diretamente, sem necessitar de uma instância da classe criada:
// TesteStatic2.java
class Classe2
{
// Escreve alguma frase na tela
public static void escreve(String msg)
{
System.out.println(msg);
}
// Retorna a multiplicação de dois números int
public static int multiplica(int n1, int n2)
{
return (n1 * n2);
}
// Construtor, apenas para mostrar que
// ele nem chega ser chamado
public Classe2()
{
System.out.println("Construtor de Classe2");
}
}
public class TesteStatic2
{
public static void main(String args[])
{
Classe2.escreve("Multiplicando 3 vezes 3:");
int resultado = Classe2.multiplica(3, 3);
Classe2.escreve("Resultado: "+ resultado);
}
}
Rode este programa e repare no resultado. Veja que o construtor da classe não foi chamado, pois não aparece na tela a string "Construtor de Classe2". Repare também que não criamos instância alguma de Classe2 para chamar seus métodos. Caso os métodos
escreve e
multiplica não fossem
static, seria necessário fazer.
public class TesteStatic2
{
public static void main(String args[])
{
Classe2 c2 = new Classe2();
c2.escreve("Multiplicando 3 vezes 3:");
int resultado = c2.multiplica(3, 3);
c2.escreve("Resultado: "+ resultado);
}
}
Note que o código acima funciona perfeitamente mesmo com os métodos static. Isso funciona porque apesar de podermos chamar diretamente as coisas quando elas são
static, não é obrigatório, podendo perfeitamente ser criada uma instância da classe e então chamar os métodos. O uso de
static depende muito do caso, e conforme você vai pegando mais experiência, irá naturalmente identificar os lugares que precisam - ou que são mais convenientes - ao uso de tal palavra-chave