【问题标题】:Scope of variable instantiated inside a method - Java在方法内实例化的变量范围 - Java
【发布时间】:2023-03-19 07:18:02
【问题描述】:

这段代码在 Java 中安全吗?

public class HelloWorld {

    public static void main (String args[]) {
        HelloWorld h = new HelloWorld();
        int y = h.getNumber(5);
        int z = h.getNumber (6);
        if (y == 10)
            System.out.println("true"); 
    }

    public int getNumber(int x) {
        int number = 5;
        number = number + x;
        return number;
    }

}

我的同事说 int number 将被放置在堆栈中,当 getNumber 返回时,它将被弹出并可能被覆盖。

相同的代码在 C 中是否可能不安全?

【问题讨论】:

  • 是的,没关系。请您的同事解释为什么这不安全,也许您可​​以与我们分享。
  • 不要把 scope 与运行时发生的任何事情混为一谈。 Scope 是一个编译时概念,它定义了在源代码中可以使用标识符的位置。
  • 你的同事错了。
  • 您的同事可能更愿意在 getNumber 方法中返回 x+5
  • 你的同事似乎完全不知道 Java 是如何工作的。

标签: java methods scope


【解决方案1】:

HelloWorld 类没有字段,因此是不可变的。您可以从任何线程使用相同的对象多次调用getNumber(x) 函数,并且对于相同的参数,它总是会给出相同的结果。

也许您的同事正在回忆 C 中的恐怖故事,您可以在其中拥有类似 static int number 的内容,它“属于”该方法并且会被覆盖。又或许她正在考虑“通过引用返回”;即使是这样,您每次都会引用一个全新的对象,因为 number 是为每个方法调用新实例化的。

【讨论】:

    【解决方案2】:

    你的同事是正确的,但他们显然误解了正在发生的事情。

        public int getNumber(int x) {
            int number = 5;
            number = number + x;
            return number;
        }
    

    是的,5 + 5 或 5 + 6 的值将被放入堆栈,但它们不会被覆盖,它们将被正确放入 y 或 z。

    我怀疑这种混淆来自 C(这种类型代码在 C 中也可以正常工作),但对于指针而不是原语。如果操作不当,从 C 中的函数返回 malloc 的结果可能是“具有挑战性的”。

    【讨论】:

    • 在 JIT 之后,number 不太可能作为值存在于堆栈中。整个操作可能会在寄存器中完成,而不是在堆栈上。如果方法被 JIT 内联,即使是参数和返回值也会作为值在堆栈上消失。结论:同事在各方面都错了。
    • 假设了解 VM 内部结构。 JVM 在汇编器类型级别是基于堆栈的。如果它在寄存器中,或者在堆栈中,在实践中并不重要 - 重要的是该值不会被丢弃。
    猜你喜欢
    • 2011-08-22
    • 2014-03-12
    • 1970-01-01
    • 2015-11-15
    • 1970-01-01
    • 2015-02-23
    • 1970-01-01
    • 2014-10-16
    • 2011-08-09
    相关资源
    最近更新 更多