O Modificador static em Java

O uso fundamental do modificador static em Java inclui:

1. Variáveis declaradas com static pertencem à classe, podendo ser acessadas diretamente através do nome_da_classe.nome_da_variável, sem a necessidade de instanciar a classe.

2. Métodos declarados com static pertencem à classe, podendo ser chamados diretamente através do nome_da_classe.nome_do_método, sem a necessidade de instanciar a classe.

3. Variáveis e métodos static são considerados recursos estáticos da classe, sendo compartilhados entre todas as instâncias da classe.

@ Por que o JDK distribui recursos estáticos em diferentes classes em vez de colocá-los todos em uma única classe?

Existem várias razões para isso:

1. Cada classe pode ter seus próprios recursos estáticos, permitindo uma organização lógica. Por exemplo, recursos matemáticos estão em java.lang.Math, enquanto recursos relacionados a calendários estão em java.util.Calendar, tornando a estrutura mais clara.

2. Evitar conflitos de nomes. É comum que diferentes classes tenham variáveis ou métodos com nomes idênticos. Se todos os recursos estáticos estivessem em uma única classe, inevitavelmente ocorreriam colisões de nomes. A solução é organizar esses recursos em classes distintas.

3. Impedir o crescimento infinito das classes de recursos estáticos, o que tornaria o código difícil de manter.

Métodos estáticos não podem referenciar recursos não estáticos

Por exemplo, no código abaixo:

public class Exemplo
{
    private int valor = 10;
    
    public static void metodoPrincipal(String[] args)
    {
        // Erro: métodos estáticos não podem acessar atributos não estáticos
        valor = 20;
    }
}

Métodos não estáticos podem referenciar recursos estáticos

Exemplo:

public class Exemplo
{
    // Atributo estático  
    private static int valorEstatico = 15;
    
    // Método não estático
    public void metodoNaoEstatico(String[] args)
    {
        valorEstatico = 25; // Permitido
    }
}

Recursos estáticos pertencem à classe, mas existem independentemente das instâncias. Do ponto de vista do mecanismo de carregamento de classes da JVM, os recursos estáticos são carregados durante a inicialização da classe, enquanto os recursos não estáticos são carregados quando uma instância da classe é criada.

Blocos Estáticos

Os blocos estáticos são outra aplicação importante do static. Eles são usados para executar operações durante a inicialização de uma classe, assim como variáveis e métodos estáticos. O código dentro de um bloco estático é executado apenas uma vez, durante a inicialização da classe.

Três pontos importantes a considerar:

1. Qual é a ordem de execução dos métodos estáticos?

public class ClasseA
{
    private static int variavelA = metodoB();
    
    static
    {
        System.out.println("Entrando no bloco estático de A");
    }
    
    public static void main(String[] args)
    {
        new ClasseA();
    }
    
    public static int metodoB()
    {
        System.out.println("Executando ClasseA.metodoB()");
        return 1;
    }
}

O resultado da execução é:

Executando ClasseA.metodoB()
Entrando no bloco estático de A

Conclusão: Os recursos estáticos são carregados estritamente na ordem em que são definidos.

2. Atribuição e criação de variáveis estáticas

public class ClasseA
{
    static
    {
        c = 30;<br></br>        // Erro de compilação
        System.out.println(c);
    }
    
    private static int c;
}

Erro: "Cannot reference a field before it is defined" (Não é possível referenciar um campo antes de sua definição).

Conclusão: Um bloco de código estático pode atribuir valores a variáveis estáticas definidas posteriormente, mas não pode acessá-las.

3. Ordem de carregamento de blocos estáticos em herança

public class ClassePai
{
    static
    {
        System.out.println("Bloco estático da ClassePai");
    }
    
    public ClassePai()
    {
        System.out.println("Construtor da ClassePai");
    }
}

public class ClasseFilha extends ClassePai
{
    static 
    {
        System.out.println("Bloco estático da ClasseFilha");
    }
    
    public ClasseFilha()
    {
        System.out.println("Construtor da ClasseFilha");
    }
    
    public static void main(String[] args)
    {
        new ClasseFilha();
        new ClasseFilha();
    }
}

O resultado da execução:

Bloco estático da ClassePai
Bloco estático da ClasseFilha
Construtor da ClassePai
Construtor da ClasseFilha
Construtor da ClassePai
Construtor da ClasseFilha

Conclusão: Os blocos estáticos são carregados estritamente na ordem bloco estático da classe pai → bloco estático da classe filha, e são executados apenas uma vez.

Observação: Geralmente, static não pode modificar uma classe. No entanto, static pode moidficar uma classe interna, tornando-a uma classe interna estática (anônima).

import static

Esta é uma funcionalidade menos comum, raramente vista em código. Pode ser útil ao usar JUnit para simplificar asserções. O import static é uma nova feature introduzida no JDK 1.5. Esses dois keywords juntos permitem importar recursos estáticos específicos de uma classe sem a necessidade de usar nome_da_classe.nome_do_recurso. É importante notar que a sintaxe deve ser import static, e não static import. Por exemplo:

import static java.lang.Math.*;

public class Exemplo
{
    public static void main(String[] args)
    {
        System.out.println(sin(2.2));
    }
}

Isso significa que todos os recursos estáticos de Math foram importados. Dentro do método main, podemos usar sin(2.2) diretamente, sem precisar de Math.sin(2.2). É crucial incluir ".*" no final, pois sem esses caracetres, a importação não funcionaria corretamente. Claro, também podemos importar apenas um recurso específico, como o método sin de Math, em vez de todos os recursos estáticos:

import static java.lang.Math.sin;

public class Exemplo
{
    public static void main(String[] args)
    {
        System.out.println(sin(2.2));
    }
}

Sobre o import static, minha recomendação é:

1. Ele simplifica algumas operações, como importar todos os recursos estáticos de Math, reduzindo a necessidade de escrever "Math." repetidamente em código que usa frequentemente esses recursos.

2. Ele pode reduzir a legibilidade do código, pois fica menos claro de qual classe um método ou variável estática pertence.

Recomenda-se importar recursos estáticos específicos em cenários apropriados, evitando o uso do ".*" para importação.

Conhecimentos Importantes:

1. O modificador static em Java não afeta o escopo de variáveis ou métodos.

2. Embora métodos estáticos não tenham acesso a this, em métodos não estáticos podemos usar this para acessar membros estáticos.

Exemplo:

public class Teste {
 
    // Variável estática
    static int valor = 11;
 
    // Método estático
    public static void main(String[] args) {
 
        new Teste().imprimirValor();
 
    }
 
    // Método não estático
    private void imprimirValor() {
        int valorLocal = 22;
        // Usando this para acessar a variável estática
        System.out.println(this.valor);
    }
}

O resultado é: 11

Aqui, this representa o objeto atual. Ao chamar imprimirValor através de new Teste(), o objeto atual é o criado por essa expressão. Como variáveis estáticas são compartilhadas por todos os objetos, this.valor dentro de imprimirValor obviamente terá o valor 11.

Tags: java static modificadores java-básico

Publicado em 7-4 03:23