Ordem de iniciação (inicialização) de atributos static final

5 respostas
mavcunha

Comecei a estudar Java e um código me chamou a atenção:

class OrdemChamada {
        static String x = getY();
        static String y = "Oi";

        public static void main(String[] args) {
                System.out.println("antes:" + x);
                x = getY();
                System.out.println("depois:" + x);
        }
        static String getY() {
                return y;
        }
}

Executado na maneira que está temos:

antes:null
depois:Oi

No entanto se adicionarmos a palavra final na declaração de y então o código imprime:

antes:Oi
depois:Oi

Suponho que ao adicionar a palavra final à y faz com que esse atributo seja avaliado primeiro, é isto que está acontecendo? E há um padrão para este comportamento?

[]' Marco.

5 Respostas

LPJava

boa pergunta… hehe

T

Quando você usa “static final”, dá a chance ao compilador de substituir literalmente no seu código por uma constante. Ou seja: isto

class OrdemChamada {
         static String x = getY();
         static final String y = "Oi";
 
         public static void main(String[] args) {
                 System.out.println("antes:" + x);
                 x = getY();
                 System.out.println("depois:" + x);
         }
         static String getY() {
                 return y;
         }
 }

é equivalente a isto:

class OrdemChamada {
         static String x = getY();
 
         public static void main(String[] args) {
                 System.out.println("antes:" + x);
                 x = getY();
                 System.out.println("depois:" + x);
         }
         static String getY() {
                 return "Oi";
         }
 }

Isso já deu muita dor de cabeça aqui. É que em um sistema antigo as pessoas, em vez de o recompilarem inteirinho, só recompilavam um pedaço dele.
O problema é que o pedaço recompilado incluía uma constante “public static final” que foi modificada - é que o pessoal achava que dava para fazer configurações de sistemas com esse tipo de constantes. Quando isso ocorre, as classes que não foram recompiladas não recebem a modificação, e o sistema funcionou como se não houvesse havido a modificação.

1112

Fica mais fácil de entender se mostrar o que acontece se o final não estiver lá. Estou sem um visualizador de bytecode aqui, mas é algo mais ou menos assim:

class OrdemChamada {
         static String x;
         static String y;
    
         static {
              x = getY();
              y = "Oi";
         }
 
         public static void main(String[] args) {
                 System.out.println("antes:" + x);
                 x = getY();
                 System.out.println("depois:" + x);
         }
         static String getY() {
                 return y;
         }
 }

Assim que o fluxo chega no bloco static, x e y estão com o valor null e, dentro desse bloco, y passa a ter o valor “Oi”.

A palavra-chave final faz com que a variável tenha apenas um valor durante todo seu escopo, que é o valor inicializado. Assim, y já começará com o valor “Oi”, pois não poderá ter null em um momento e “Oi” em outro.

Mantu

Só o Thingol pra responder esse tipo de questão… :lol:

LPJava

thingol:
Quando você usa “static final”, dá a chance ao compilador de substituir literalmente no seu código por uma constante. Ou seja: isto

class OrdemChamada {
         static String x = getY();
         static final String y = "Oi";
 
         public static void main(String[] args) {
                 System.out.println("antes:" + x);
                 x = getY();
                 System.out.println("depois:" + x);
         }
         static String getY() {
                 return y;
         }
 }

é equivalente a isto:

class OrdemChamada {
         static String x = getY();
 
         public static void main(String[] args) {
                 System.out.println("antes:" + x);
                 x = getY();
                 System.out.println("depois:" + x);
         }
         static String getY() {
                 return "Oi";
         }
 }

Isso já deu muita dor de cabeça aqui. É que em um sistema antigo as pessoas, em vez de o recompilarem inteirinho, só recompilavam um pedaço dele.
O problema é que o pedaço recompilado incluía uma constante “public static final” que foi modificada - é que o pessoal achava que dava para fazer configurações de sistemas com esse tipo de constantes. Quando isso ocorre, as classes que não foram recompiladas não recebem a modificação, e o sistema funcionou como se não houvesse havido a modificação.

isso é o nó juizo hehe:X

Criado 1 de abril de 2007
Ultima resposta 2 de abr. de 2007
Respostas 5
Participantes 5