【问题标题】:What are captured variables in Java Local ClassesJava 本地类中捕获的变量是什么
【发布时间】:2014-02-25 20:15:24
【问题描述】:

Local Classes 的 Java 文档说:

此外,本地类可以访问本地变量。然而,一个 local 类只能访问声明为 final 的局部变量。 当一个局部类访问一个局部变量或参数时 封闭块,它捕获该变量或参数。例如, PhoneNumber 构造函数可以访问局部变量 numberLength 因为它被宣布为最终的; numberLength 是一个捕获的变量。

什么是捕获变量,它的用途是什么,为什么需要它?请帮助我理解它的概念。

【问题讨论】:

标签: java


【解决方案1】:

这是一篇描述它的帖子:http://www.devcodenote.com/2015/04/variable-capture-in-java.html

这是帖子中的一个sn-p:

“Java 强制规定,如果在方法中定义的内部类引用了该方法的局部变量,则该局部变量应定义为 final。”

这是因为函数可能完成执行并从进程堆栈中删除,所有变量都已销毁,但内部类的对象可能仍在堆上引用该函数的特定局部变量。为了解决这个问题,Java 制作了一个局部变量的副本,并将其作为对内部类的引用。为了保持两个副本之间的一致性,局部变量被强制为“最终”且不可修改。

【讨论】:

  • 难得一见。非常感谢
  • 我真的不明白为什么这个简单而超级清晰的答案没有得到太多支持。
【解决方案2】:

什么是捕获变量,它的用途是什么,为什么需要它?

捕获的变量是一个被复制的变量,因此它可以在嵌套类中使用。必须复制它的原因是对象可能超出当前上下文。它必须是 final(或者在 Java 8 中实际上是 final),因此不会混淆是否会看到对变量的更改(因为它们不会)

注意:Groovy 确实有这个规则,对局部变量的更改可能意味着对封闭类中的值的更改,如果涉及多个线程,这尤其令人困惑。

一个捕获变量的例子。

public void writeToDataBase(final Object toWrite) {
    executor.submit(new Runnable() {
        public void run() {
             writeToDBNow(toWrite);
        }
    });
    // if toWrite were mutable and you changed it now, what would happen !?
}
// after the method returns toWrite no longer exists for the this thread...

【讨论】:

  • 您能否澄清(或举例)对象(哪个对象?)在当前上下文中的寿命?
  • 非常感谢 Peter,你能给我一个 Java 程序的例子,解释对象如何比上下文更长寿,这导致 Java 的设计者限制变量是最终的或有效的最终。
  • @user2065083 添加了一个外出生活的例子,并给出了这样做的理由。不知道如何使它更清楚。
  • 感谢彼得提供了一个例子,但我对多线程/并发的了解最少,所以我很难理解。我期待其他一些基本示例,或者更常用的是使用 Java 的 Comparator 接口的示例。
  • @user2065083 比较器通常是无状态的。给他们捕获的变量是很少见的。
【解决方案3】:

捕获的变量是来自本地类外部的变量 - 在周围块中声明的变量。在某些语言中,这称为closure.

在来自the Oracle Docs(简化)的示例中,在PhoneNumber 类外部 声明的变量numberLength 被“捕获”。

final int numberLength = 10;  // in JDK7 and earlier must be final...

class PhoneNumber {
   // you can refer to numberLength here...  it has been "captured"
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-02-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-11-08
    • 2021-10-04
    • 2019-12-14
    相关资源
    最近更新 更多