A variável usada na expressão lambda deve ser final ou efetivamente final
Quando tento usá- calTz
lo, está mostrando esse erro.
private TimeZone extractCalendarTimeZoneComponent(Calendar cal, TimeZone calTz) {
try {
cal.getComponents().getComponents("VTIMEZONE").forEach(component -> {
VTimeZone v = (VTimeZone) component;
v.getTimeZoneId();
if (calTz == null) {
calTz = TimeZone.getTimeZone(v.getTimeZoneId().getValue());
}
});
} catch (Exception e) {
log.warn("Unable to determine ical timezone", e);
}
return null;
}
calTz
partir do lambda.Respostas:
Uma
final
variável significa que ela pode ser instanciada apenas uma vez. em Java, você não pode usar variáveis não finais no lambda, bem como em classes internas anônimas.Você pode refatorar seu código com o antigo loop for-each:
Mesmo que eu não entenda algumas partes deste código:
v.getTimeZoneId();
sem usar seu valor de retornocalTz = TimeZone.getTimeZone(v.getTimeZoneId().getValue());
você não modifica o originalmente aprovadocalTz
e não o usa neste métodonull
, por que não definevoid
como tipo de retorno?Espero que essas dicas também ajudem você a melhorar.
fonte
Embora outras respostas provem o requisito, elas não explicam por que o requisito existe.
O JLS menciona por que, em § 15.27.2 :
Para diminuir o risco de bugs, eles decidiram garantir que as variáveis capturadas nunca fossem mutadas.
fonte
De um lambda, você não pode obter uma referência a nada que não seja final. Você precisa declarar um wrapper final de fora do lamda para manter sua variável.
Eu adicionei o objeto 'referência' final como este wrapper.
fonte
reference.set(calTz);
ou a referência deve ser criada usandonew AtomicReference<>(calTz)
, caso contrário, o TimeZone não nulo fornecido como parâmetro será perdido.O Java 8 tem um novo conceito chamado variável "Efetivamente final". Isso significa que uma variável local não final, cujo valor nunca muda após a inicialização, é chamada "Efetivamente Final".
Esse conceito foi introduzido porque, antes do Java 8 , não era possível usar uma variável local não final em uma classe anônima . Se você quiser ter acesso a uma variável local na classe anônima , precisará finalizá-la.
Quando o lambda foi introduzido, essa restrição foi facilitada. Portanto, a necessidade de tornar a variável local final se ela não for alterada, uma vez que é inicializada como lambda em si, não passa de uma classe anônima.
O Java 8 percebeu a dificuldade de declarar a variável local final toda vez que um desenvolvedor usou o lambda, introduziu esse conceito e tornou desnecessário finalizar as variáveis locais. Portanto, se você vê que a regra para classes anônimas não mudou, é só que você não precisa escrever a
final
palavra-chave sempre que usar lambdas.Eu encontrei uma boa explicação aqui
fonte
effectively final
não é código, é terminologia. Consulte Quando a formatação de código deve ser usada para texto sem código? no Meta Stack Overflow .final
palavra - chave" é uma palavra de código e correta para formatar dessa maneira, mas quando você usa "final" descritivamente, e não como código, é uma terminologia).No seu exemplo, você pode substituir o
forEach
with lamdba por umfor
loop simples e modificar qualquer variável livremente. Ou, provavelmente, refatorar seu código para que você não precise modificar nenhuma variável. No entanto, explicarei por completo o que significa o erro e como solucionar o problema.Especificação da linguagem Java 8, §15.27.2 :
Basicamente, você não pode modificar uma variável local (
calTz
neste caso) de dentro de uma lambda (ou uma classe local / anônima). Para conseguir isso em Java, você deve usar um objeto mutável e modificá-lo (por meio de uma variável final) a partir do lambda. Um exemplo de um objeto mutável aqui seria uma matriz de um elemento:fonte
se não for necessário modificar a variável, uma solução geral para esse tipo de problema seria extrair a parte do código que usa lambda e usa a palavra-chave final no método-parâmetro.
fonte
Uma variável usada na expressão lambda deve ser final ou efetivamente final, mas você pode atribuir um valor a uma matriz final de um elemento.
fonte