Referindo-se à não-de-final, os campos de uma classe envolvente dentro de uma classe interna anônima em Java
-
20-09-2019 - |
Pergunta
Em Java, eu sei que é possível fazer algo parecido com isso:
public class Greeter {
public void greetEventually() {
final String greeting = "Hello!";
Job j = new Job() {
public void run() {
System.out.println(greeting);
}
};
j.schedule();
}
}
Este seria executado anônimo Job
em algum ponto no futuro.Isso funciona porque o anônimo classes são autorizados a consultar finais variáveis no âmbito envolvente.
O que eu não tenho certeza sobre o seguinte caso:
public class Greeter {
private String greeting;
// ... Other methods that might mutate greeting ...
public void greetEventually() {
Job j = new Job() {
public void run() {
System.out.println(greeting);
}
};
j.schedule();
}
}
Neste caso, meu anônimo Job
está se referindo a um não-campo final da classe envolvente.Quando o Trabalho for executado, será que vou ver o valor do greeting
campo como ele era quando o Trabalho foi criado, ou como ele é quando está em execução?Eu acho que eu sei a resposta, mas eu pensei que era uma pergunta interessante, e em primeiro lugar ele me deixou e de um par de colegas de trabalho de segunda a adivinhar-nos por alguns minutos.
Solução
Você vai ver que o valor de greeting
como ele é quando o anônimo Job
executa.
O final
o modificador é necessário apenas para as variáveis locais, não variáveis de membro.
Outras dicas
Você está acessando o campo através do (a externa) this
).Você pode pensar this
como, efetivamente, final
variável local.Somente o local é final
, o objeto apontado não é (necessariamente) constante.Imagine uma variável local com o mesmo valor this
e ele deve ser criptografado.
public class Greeter {
private String greeting;
// ... Other methods that might mutate greeting ...
public void greetEventually() {
private final Greeter greeter = this; // <---
Job j = new Job() {
public void run() {
System.out.println( greeter.greeting ); // <---
}
};
j.schedule();
}
}
O final modificador é aplicado para as variáveis locais só para fornecer variáveis para cada instância da classe interna, então podemos usar:final String saudação;
Quando você precisa de apenas uma instância de uma variável (como no caso de constantes ou recursos comuns), use:Cadeia privada de saudação;