class Test {
public static void main(String arg[]) {
System.out.println("**MAIN METHOD");
System.out.println(Mno.VAL); // SOP(9090);
System.out.println(Mno.VAL + 100); // SOP(9190);
}
}
class Mno {
final static int VAL = 9090;
static {
System.out.println("**STATIC BLOCK OF Mno\t: " + VAL);
}
}
Eu sei que um static
bloco é executado quando a classe é carregada. Mas, neste caso, a variável de instância dentro da classe Mno
é final
, por isso o static
bloco não está executando.
Por que? E se eu removesse o final
, funcionaria bem?
Qual memória será alocada primeiro, a static final
variável ou o static
bloco?
Se devido ao final
modificador de acesso a classe não for carregada, então como a variável pode obter memória?
java
static
access-modifiers
Sthita
fonte
fonte
Respostas:
static final int
campo é uma constante de tempo de compilação e seu valor é codificado na classe de destino sem uma referência à sua origem;Em detalhes específicos, o bytecode compilado corresponde a este:
Assim que você remove
final
, ele não é mais uma constante de tempo de compilação e o comportamento especial descrito acima não se aplica. AMno
classe é carregada conforme o esperado e seu inicializador estático é executado.fonte
A razão pela qual a classe não é carregada é que
VAL
éfinal
E ela é inicializada com uma expressão constante (9090). Se, e somente se, essas duas condições forem atendidas, a constante é avaliada em tempo de compilação e "codificada" quando necessário.Para evitar que a expressão seja avaliada em tempo de compilação (e para fazer a JVM carregar sua classe), você pode:
remova a palavra-chave final:
ou altere a expressão do lado direito para algo não constante (mesmo se a variável ainda for final):
fonte
Se você
javap -v Test.class
vir bytecode gerado usando , main () será assim:Você pode ver claramente em "
11: sipush 9090
" que o valor final estático é usado diretamente, porque Mno.VAL é uma constante de tempo de compilação. Portanto, não é necessário carregar a classe Mno. Portanto, o bloco estático de Mno não é executado.Você pode executar o bloco estático carregando manualmente o Mno como abaixo:
fonte
Na verdade, você não estendeu essa classe Mno, então quando começar a compilação ela irá gerar uma constante da variável VAL e quando a execução começar quando essa variável for necessária, ela será carregada da memória. Portanto, não é necessário que sua classe faça referência para que o bock estático não seja executado.
se a classe
A
estende a classeMno
, o bloco estático é incluído na classe.A
Se você fizer isso, esse bloco estático será executado. Por exemplo..fonte
Pelo que eu sei, ele será executado em ordem de aparecimento. Por exemplo :
irá imprimir
Acabei de testá-lo e os estáticos são inicializados (=> imprimir) quando a classe "Statique" é realmente usada e "executada" em outro trecho de código (no meu caso eu fiz "new Statique ()".
fonte
Statique
classe fazendonew Statique()
. Enquanto na pergunta feita, aMno
classe não foi carregada.