Referindo-se à não-de-final, os campos de uma classe envolvente dentro de uma classe interna anônima em Java

StackOverflow https://stackoverflow.com/questions/2248970

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.

Foi útil?

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;

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top