count
campo for estático na Counter
classe, significa que você pode referenciar a variável com a seguinte expressão: Counter.count
. 
private
os campos estão disponíveis apenas dentro da classe em que são declarados. E protected
os campos estão disponíveis para todas as classes dentro de um pacote, bem como para todas as suas subclasses fora do pacote. Suponha que a Counter
classe tenha um método estático increment()
cujo trabalho seja incrementar ocount
campo. Para chamar esse método, você pode usar Counter.increment()
. Não há necessidade de criar uma instância da Counter
classe para acessar um campo ou método estático. Esta é a diferença fundamental entre variáveis e métodos estáticos (classe) e variáveis e métodos NÃO estáticos (instância). Uma observação importante. Não esqueça que os membros estáticos da classe pertencem diretamente à classe, não a qualquer instância da classe. Ou seja, o valor da count
variável estática será o mesmo para todos Counter
os objetos. Neste artigo, veremos os aspectos fundamentais do uso do modificador estático em Java, bem como alguns recursos que ajudarão você a entender os principais conceitos de programação.
O que todo programador deve saber sobre o modificador estático em Java.
Nesta seção, examinamos os principais aspectos do uso de métodos, campos e classes estáticos. Vamos começar com as variáveis.-
Você NÃO PODE acessar membros não estáticos de uma classe dentro de um contexto estático, como um método ou bloco estático. Compilar o código abaixo resultará em um erro:
public class Counter { private int count; public static void main(String args []) { System.out.println(count); // Compile time error } }
Este é um dos erros mais comuns cometidos por programadores Java, especialmente iniciantes. Como o
main
método é estático e acount
variável não, usar oprintln
método dentro domain
método produzirá um "erro de tempo de compilação". -
Ao contrário das variáveis locais, campos e métodos estáticos NÃO estão
thread safe
em Java. Na prática, essa é uma das causas mais frequentes de problemas de segurança na programação multithread. Considerando que cada instância de uma classe referencia a mesma cópia de uma variável estática, tal variável precisa ser protegida ou "bloqueada" pela classe. Portanto, ao usar variáveis estáticas, verifique se elas estão corretassynchronized
para evitar problemas comorace conditions
. -
Os métodos estáticos têm uma vantagem prática, pois não há necessidade de criar um novo objeto toda vez que você deseja chamá-los. Um método estático pode ser chamado usando o nome da classe que o declara. É por isso que esses métodos são perfeitos para
factory
métodos eutility
métodos. Ajava.lang.Math
classe é um exemplo maravilhoso: quase todos os seus métodos são estáticos. As classes utilitárias de Java são marcadasfinal
pelo mesmo motivo. -
Outro ponto importante é que você não pode sobrescrever (
@Override
) métodos estáticos. Se você declarar tal método em umsubclass
, ou seja, um método com o mesmo nome e assinatura, você apenas "ocultará" o métodosuperclass
em vez de substituí-lo. Este fenômeno é conhecido comomethod hiding
. Isso significa que, se um método estático for declarado nas classes pai e filha, o método chamado sempre será baseado no tipo de variável em tempo de compilação. Ao contrário da substituição de método, esses métodos não serão executados quando o programa for executado. Vamos considerar um exemplo:class Vehicle { public static void kmToMiles(int km) { System.out.println("Inside the parent class / static method"); } } class Car extends Vehicle { public static void kmToMiles(int km) { System.out.println("Inside the child class / static method"); } } public class Demo { public static void main(String args []) { Vehicle v = new Car(); v.kmToMiles(10); } }
Saída do console:
Dentro da classe pai/método estático
O código demonstra claramente que, apesar do objeto ser um
Car
, o método estático naVehicle
classe é chamado, pois o método foi chamado em tempo de compilação. E observe que não houve erros de compilação! -
Além do mais, além das classes de nível superior, você pode declarar classes estáticas. Essas classes são conhecidas como
nested static classes
. Eles são úteis para fornecer uma melhor coesão. Um exemplo marcante de uma classe estática aninhada éHashMap.Entry
, que é uma estrutura de dados dentro deHashMap
. Vale a pena observar que, assim como as classes internas, as classes aninhadas estáticas são declaradas em um arquivo .class separado. Assim, se você declarar cinco classes aninhadas em sua classe principal, você terá 6 arquivos com a extensão .class. Outro exemplo é a declaração do nosso próprioComparator
, como um comparador de idade (AgeComparator
) naEmployee
classe. -
O modificador static também pode ser especificado em um bloco estático, mais conhecido como "bloco de inicialização estático", que é executado quando a classe é carregada. Se você não declarar tal bloco, o Java coletará todos os campos estáticos em uma única lista e os inicializará quando a classe for carregada. Um bloco estático NÃO PODE lançar exceções verificadas, mas pode lançar exceções não verificadas. Neste caso,
ExceptionInInitializerError
ocorrerá um. Na prática, qualquer exceção que ocorra durante a inicialização de campos estáticos será encapsulada neste erro pelo Java. Essa também é a causa mais comum doNoClassDefFoundError
, porque a classe não estará na memória quando for referenciada. -
É útil saber que os métodos estáticos são vinculados em tempo de compilação, ao contrário da vinculação de métodos virtuais ou não estáticos, que são vinculados em tempo de execução quando chamados em um objeto real. Da mesma forma, os métodos estáticos não podem ser substituídos em Java, pois o polimorfismo não se aplica a eles em tempo de execução. Essa é uma limitação importante a ser considerada ao declarar um método estático. Fazer isso só faz sentido quando não há habilidade ou necessidade de sobrescrever o método em uma subclasse. Métodos de fábrica e métodos utilitários são bons exemplos de uso adequado do modificador estático. Joshua Bloch aponta várias vantagens que os métodos estáticos de fábrica têm sobre os construtores em seu livro Effective Java, que é leitura obrigatória para todo programador Java.
-
A inicialização é um aspecto importante de um bloco estático. Campos estáticos ou variáveis são inicializados depois que a classe é carregada na memória. A ordem de inicialização é de cima para baixo, na mesma ordem em que são declaradas no arquivo fonte da classe Java. Como os campos estáticos são inicializados de maneira thread-safe, esse processo também é usado para implementar o
Singleton
padrão. Se você não estiver usando umEnum
como aSingleton
por algum motivo, terá uma boa alternativa. Mas, neste caso, você deve levar em consideração que não se trata de uma inicialização "preguiçosa". Isso significa que o campo estático será inicializado mesmo ANTES de alguém "pedir" por ele. Se um objeto tiver muitos recursos ou for raramente usado, inicializá-lo em um bloco estático não funcionará a seu favor. -
Durante a serialização, campos estáticos, como
transient
variáveis, não são serializados. De fato, se você salvar quaisquer dados em um campo estático, ele conterá seu valor inicial (padrão) após a desserialização. Por exemplo, se um campo estático for umint
, seu valor será zero após a desserialização. Se seu tipo forfloat
, o valor será 0,0. Se o campo for umObject
, o valor seránull
. Para ser honesto, esta é uma das perguntas mais frequentes sobre serialização em entrevistas para cargos Java. Não armazene dados de objetos essenciais em um campo estático! -
Finalmente, vamos falar sobre importação estática. Esse modificador tem muito em comum com a
import
instrução padrão, mas é diferente porque permite importar um ou todos os membros estáticos da classe. Depois que os métodos estáticos são importados, eles podem ser acessados como se fossem declarados na mesma classe. Da mesma forma, importando campos estáticos, podemos acessá-los sem especificar o nome da classe. Esse recurso apareceu no Java 1.5 e melhora a legibilidade do código quando usado corretamente. Essa construção é encontrada com mais frequência em testes JUnit, já que quase todos os desenvolvedores de teste usam importação estática para métodos assert, por exemplo,assertEquals()
e suas variantes sobrecarregadas. -
É tudo por agora. Todo programador Java precisa conhecer todos os aspectos do modificador estático mencionado acima. Este artigo revisou informações básicas sobre variáveis estáticas, campos, métodos, blocos de inicialização e importações. Ele também tocou em algumas propriedades importantes que são essenciais para escrever e entender programas Java. Espero que cada desenvolvedor aperfeiçoe seu uso habilidoso de membros estáticos, porque é muito importante para o desenvolvimento de software sério."
GO TO FULL VERSION