java - 添加范围 {} 括号让变量超出范围是否与调用和结束函数或某种空循环具有相同的效果?

标签 java scope stack brackets

我想知道是否可以让变量超出范围,而只在某些代码段周围添加方括号,它是否与其他让变量超出范围的方法有什么不同:

0) 添加括号:

private void methodExample() {
    {
        int example = 5;
    }
    //variable "example" out of scope
}

1)函数调用:

private void methodExample() {        
    justMakeItAMethod();
    //variable "example" out of scope
}

private void justMakeItAMethod() {
        int example = 5;
}

2) 循环结束如下:

private void methodExample() {
    do {
        int example = 5;
    } while (false);
    //variable "example" out of scope
}

变量超出堆栈范围的方式是否因示例而异?

我想到这个的原因:[免责声明我知道这是过早优化的情况]我有一个低级函数,其中我有许多不同的小的独立代码部分,功能略有不同,不够我的意见是让它成为一个不同的函数,这将需要一个函数调用开销,但足够多的部分宁愿变量已经超出范围。

最佳答案

行为可能会有所不同,具体取决于您使用的是解释框架还是 JIT 编译框架。在 JIT 编译的框架中,对象可以在最后一次使用变量后标记为空闲,即使它仍在范围内。参见 this answer例如。在解释帧中,即使在范围结束后,它仍将驻留在堆栈帧变量槽中。另一方面,编译器重用在作用域结束时释放的变量槽。这可能会导致解释帧的有趣结果:

public class LVTest {
    @Override
    protected void finalize() {
        System.out.println("Finalized");
    }

    public static void main(String[] args) throws InterruptedException {
        {
            LVTest t = new LVTest();
        }
        System.out.println("GC!");
        System.gc();
        Thread.sleep(1000);
        System.out.println("GC!");
        System.gc();
        Thread.sleep(1000);
        System.out.println("GC!");
        System.gc();
        Thread.sleep(1000);
        System.out.println("Assign new var!");
        int a = 5;
        System.out.println("GC!");
        System.gc();
        Thread.sleep(1000);
        System.out.println("Finish");
    }
}

输出是这样的:

GC!
GC!
GC!
Assign new var!
GC!
Finalized
Finish

因此无论我们收集多少次垃圾,我们的范围外对象都不会最终确定。但是在我们分配一个重用相同变量槽的新变量之后,我们最终可以释放原始变量。如果此方法是 JIT 编译的,则 Finalized 消息会更早出现。

在任何情况下,“scope end”在字节码中都被编译为空,因此 JVM 不知道您在哪里关闭花括号。如果您认为您的代码将在解释框架中执行,那么在使用后将 null 分配给变量可能比使用 block 并希望在它之后创建新变量更安全。尽管如果您的方法的一部分执行了很长时间并且不使用以前创建的变量,那么将您的方法拆分为更小的部分会更好。在 JIT 编译的框架中,您根本不应该对其进行优化:JIT 编译器很聪明。

关于java - 添加范围 {} 括号让变量超出范围是否与调用和结束函数或某种空循环具有相同的效果?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30119013/

相关文章:

c - C中程序的错误答案(中缀符号->后缀符号)

java - 如何将表中的数据写入静态 block 中?

java - 如何检测 android 屏幕上的触摸位置?

c - 在C中的嵌套 block 中重新声明标识符

c# - 我怎样才能让一个函数修改一个变量C#

algorithm - 如何跟踪迭代(非递归)函数的嵌套信息

Linux 上的 Java Paths.get() 奇怪行为

java - 如何从 Java 中的相对路径运行可执行文件

c - C 的三元条件运算符是否创建新范围?

c - C 中此通用堆栈实现的 "free"函数有什么问题?