lambda 表达式中使用的变量应为最终或有效最终

2022-08-31 06:16:20

lambda 表达式中使用的变量应为最终或有效最终

当我尝试使用它时,它会显示此错误。calTz

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;
}

答案 1

虽然其他答案证明了这个要求,但它们并没有解释为什么存在这个要求。

JLS在§15.27.2中提到了为什么:

对有效最终变量的限制禁止访问动态变化的局部变量,这些局部变量的捕获可能会引入并发问题。

为了降低 bug 的风险,他们决定确保捕获的变量永远不会发生变异。


这也适用于匿名内部类


答案 2

变量意味着它只能实例化一次。在Java中,您无法在lambda和匿名内部类中重新分配非最终局部变量。final

您可以使用旧的 for-each 循环重构代码:

private TimeZone extractCalendarTimeZoneComponent(Calendar cal,TimeZone calTz) {
    try {
        for(Component component : cal.getComponents().getComponents("VTIMEZONE")) {
        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;
}

即使我感觉不到这段代码的某些部分:

  • 您在不使用其返回值的情况下调用 av.getTimeZoneId();
  • 对于分配,您不会修改最初通过的分配,也不会在此方法中使用它calTz = TimeZone.getTimeZone(v.getTimeZoneId().getValue());calTz
  • 你总是返回,为什么不设置为返回类型?nullvoid

希望这些提示也能帮助您提高。


推荐