首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >Java是否将方法参数复制到被调用方法的堆栈框架中?

Java是否将方法参数复制到被调用方法的堆栈框架中?
EN

Software Engineering用户
提问于 2017-05-28 11:43:36
回答 2查看 3.8K关注 0票数 2

这是答案中关于堆栈和堆的一部分:

那么,为什么有堆栈或堆呢?对于离开作用域的东西,堆栈可能会很昂贵。考虑代码: void (String){ bar( arg);.} void (String){ qux( arg);.} void (String){.}参数也是堆栈的一部分。在没有堆的情况下,将在堆栈上传递完整的值集。这是好的“福”和小弦乐..。但是,如果有人在这个字符串中放了一个巨大的XML文件,会发生什么。每个调用都会将整个庞大的字符串复制到堆栈上--这将是相当浪费的。

这就是我在Java虚拟机规范8版中所读到的(第2.5.2章)。( Java虚拟机堆栈):

Java虚拟机栈保存局部变量和部分结果,并在方法调用和返回中发挥作用。

我所知道的是,当我将引用作为参数传递给方法时,会在方法中创建一个局部变量。局部变量与传递的变量具有相同的引用。例如,像这样的事情

代码语言:javascript
运行
复制
void foo(Bar bar) {
    // Do something with bar
}

变成这样:

代码语言:javascript
运行
复制
void foo(Bar bar) {
    Bar localBar = bar;
    // Do something with localBar
}

所以我的问题是:

Java是否将方法参数复制到被调用方法的堆栈框架中?我在页面开头提到的答案中,我知道它们是复制的,这是一个很深的副本。几乎可以肯定,我错了。

EN

回答 2

Software Engineering用户

回答已采纳

发布于 2017-05-28 12:13:31

在Java中,堆栈和堆的区别并不是很有意义,因为Java没有给您选择值所在的位置。从概念上讲,所有对象都生活在堆中的某个地方,但在Java中,对象与变量不是同一回事。局部变量和方法参数使用堆栈上的空间,但变量从不直接持有对象。这些变量要么包含像int这样的原始值,要么包含对对象的引用。

在Java中,变量赋值总是执行浅拷贝:对于原始值,值被复制。对于对象,引用将被复制。引用的对象不被复制:原始引用和复制引用都引用同一个对象。

方法调用非常类似于对参数的变量赋值。调用方法时,可以认为在堆栈上分配了带有方法参数的堆栈帧,然后我们将参数值分配给每个参数变量。

由于执行了所有参数值的浅拷贝,所以不能通过向方法中的参数赋值来更改外部变量:

代码语言:javascript
运行
复制
void outer() {
  int i = 4;
  inner(i);
  // i will always be 4 at this point
}

void inner(int j) {
  j = 7;  // this assignment only affects the *local* j
}

但是,如果传递一个对象,则不存在深度复制,因此对对象的更改在方法之外是可见的:

代码语言:javascript
运行
复制
void outer() {
  ArrayList<String> xs = new ArrayList<>();
  inner(xs);
  // xs has been modified at this point, and contains "foo"
}

void inner(ArrayList<String> ys) {
  ys.add("foo");
}

您所引用的答案中的部分并不解释Java是如何工作的,而是为什么不对每个方法调用进行深度复制。

Java的方法调用的行为非常类似于C和C++:一切都是通过值传递的。不同之处在于,Java对象不是C和C++意义上的对象,而是像指向实际对象的指针。对于变量赋值和方法调用,然后通过值传递该指针。

票数 7
EN

Software Engineering用户

发布于 2017-05-28 12:31:35

在Java中,您有对象(所有继承自java.lang.Object,堆分配)和基元类型(boolchar、整数类型、floatdouble,以及指向对象的指针(称为营销引用))。

变量是基本类型的,因此很少复制,并且总是通过值传递。

对象根本不能传递,但是指向它们的指针可以通过引用有效地传递它们,而不是复制它们。

基元类型的深拷贝与浅拷贝相同。

除非您显式地创建对象,否则不会发生对象的副本,那么您自己就有责任在适当的情况下执行/避免结构共享。

票数 0
EN
页面原文内容由Software Engineering提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://softwareengineering.stackexchange.com/questions/349731

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档