La variable utilizada en la expresión lambda debe ser final o efectivamente final
Cuando intento usarlo calTz
, muestra este error.
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
desde la lambda.Respuestas:
Una
final
variable significa que solo se puede instanciar una vez. en Java no puede usar variables no finales en lambda ni en clases internas anónimas.Puede refactorizar su código con el antiguo ciclo for-each:
Incluso si no entiendo algunas partes de este código:
v.getTimeZoneId();
sin usar su valor de retornocalTz = TimeZone.getTimeZone(v.getTimeZoneId().getValue());
, no modifica el aprobado originalmentecalTz
y no lo usa en este métodonull
, ¿por qué no configurasvoid
como tipo de retorno?Espero que también estos consejos te ayuden a mejorar.
fuente
Aunque otras respuestas prueban el requisito, no explican por qué existe el requisito.
El JLS menciona por qué en §15.27.2 :
Para reducir el riesgo de errores, decidieron asegurarse de que las variables capturadas nunca se muten.
fuente
De una lambda, no puedes obtener una referencia a nada que no sea definitivo. Debe declarar un contenedor final desde fuera del lamda para mantener su variable.
He agregado el objeto de 'referencia' final como este contenedor.
fuente
reference.set(calTz);
o la referencia debe crearse utilizandonew AtomicReference<>(calTz)
, de lo contrario, se perderá la TimeZone no nula proporcionada como parámetro.Java 8 tiene un nuevo concepto llamado variable "Efectivamente final". Significa que una variable local no final cuyo valor nunca cambia después de la inicialización se llama "Efectivamente Final".
Este concepto se introdujo porque antes de Java 8 , no podíamos usar una variable local no final en una clase anónima . Si desea tener acceso a una variable local en clase anónima , debe hacerlo final.
Cuando se introdujo lambda, esta restricción se alivió. Por lo tanto, la necesidad de hacer que la variable local sea final si no se cambia una vez que se inicializa como lambda en sí misma no es más que una clase anónima.
Java 8 se dio cuenta de la molestia de declarar la variable local final cada vez que un desarrollador usaba lambda, introdujo este concepto e hizo innecesario hacer que las variables locales fueran finales. Entonces, si ve que la regla para las clases anónimas no ha cambiado, es solo que no tiene que escribir la
final
palabra clave cada vez que usa lambdas.Encontré una buena explicación aquí
fuente
effectively final
No es código, es terminología. Consulte ¿ Cuándo se debe usar el formato de código para texto sin código? en Meta Stack Overflow .final
palabra clave" es una palabra de código y correcta para formatear de esa manera, pero cuando usa "final" descriptivamente en lugar de como código, es la terminología en su lugar).En su ejemplo, puede reemplazar el
forEach
con lamdba con unfor
bucle simple y modificar cualquier variable libremente. O, probablemente, refactorice su código para que no necesite modificar ninguna variable. Sin embargo, explicaré por completo qué significa el error y cómo solucionarlo.Especificación del lenguaje Java 8, §15.27.2 :
Básicamente no puede modificar una variable local (
calTz
en este caso) desde una lambda (o una clase local / anónima). Para lograr eso en Java, debe usar un objeto mutable y modificarlo (a través de una variable final) desde la lambda. Un ejemplo de un objeto mutable aquí sería una matriz de un elemento:fuente
Si no es necesario modificar la variable, una solución general para este tipo de problema sería extraer la parte del código que utiliza lambda y la palabra clave final en el método-parámetro.
fuente
Una variable utilizada en la expresión lambda debe ser una final o efectivamente final, pero puede asignar un valor a una matriz de un elemento final.
fuente