当我们在函数内部声明一个类并且还创建该类的变量时,该类的对象是否被压入堆栈或堆中?在内部类的上下文中使用时,我对使用final关键字有些困惑吗?如果变量和类对象都存在于堆栈中,那么为什么我们需要将变量命名为final?
亲切的问候。
答案 0 :(得分:1)
当我们在函数内部声明一个类并且还创建该类的变量时,该类的对象是否被压入堆栈或堆中?
您的术语不正确,这可能是您混淆的根源:
类的声明不会导致分配任何空间...除了用于表示在加载和初始化类时发生的代码,静态等的空间的一次性分配。 / p>
Java有方法,而不是函数。
在方法(即局部变量)中声明变量时,变量本身的空间将在堆栈上分配。 (如果声明静态变量或实例变量,则该空间将成为堆节点的一部分。)
当您创建类的实例(即对象)时,该实例的空间将分配在堆 1 上。该实例的引用可以分配给堆栈上的先前分配的变量...(对于方法中的局部变量)或堆(对于静态或实例变量)...但是它也可以立即丢弃。无论哪种方式,引用的空间分配都与实例的创建无关。
在内部类的上下文中使用时,我对使用final关键字有些困惑吗?如果变量和类对象都存在于堆栈中,那么为什么我们需要将变量命名为final?
final
是必需的,因为Java不支持正确的闭包。当内部类引用封闭范围中的 local 变量时,会发生的变化是将变量的值传递给内部类并存储在隐藏变量中。 final
允许编译器有效地将其隐藏在应用程序中。由于应用程序无法更改变量的内容,因此无法判断变量 2 有两个副本。
1 - 这有点过于简单化了。如果您有兴趣,请阅读“逃逸分析”。
2 - 这是局部变量存储在堆栈中的规则的例外。在这种情况下,变量的副本也存储在内部类实例的堆节点中。然而,这是一个实现细节......就像所有堆栈对堆的东西一样。如果更改了JVM体系结构以支持闭包,那么事情可能会有所不同。