java - 更改 Java 中传递的参数(通过 ref、value 调用)

标签 java parameter-passing

我实际上认为我对 Java 中传递值的实际工作方式有一个很好的了解,因为那是我通过的 SCJP 证书的一部分。直到今天,我在工作中发现了这样一个方法:

public void toCommand(Stringbuffer buf) {

  buf.append("blablabla");
}

然后该方法的调用者使用如下函数:

StringBuffer buf = new StringBuffer();
toCommand(buf);
String str = buf.toString();

现在我认为该代码会给 str 赋值“”,但它实际上给了它方法中的值。这怎么可能?我认为事情在 Java 中不是那样工作的?

不管怎样……用 Java 编写这样的代码应该被认为是一种不好的做法,对吧?因为我可以想象它会带来一些困惑。

我实际上花了一些时间搜索这个,但我对这些消息来源的解释是,它不应该起作用。我错过了什么?

http://www.yoda.arachsys.com/java/passing.html
http://javadude.com/articles/passbyvalue.htm

塞巴斯蒂安

最佳答案

Java 是按值传递的。对象引用的 是对象引用,而不是对象本身。因此 toCommand 方法接收到该值的副本,该副本是对该对象的引用——调用者引用的同一对象。

这与从两个变量引用一个对象时完全相同:

StringBuffer buf1;
StringBuffer buf2;

buf1 = new StringBuffer();
buf2 = buf1; // Still ONE object; there are two references to it
buf1.append("Hi there");   
System.out.println(buf2.toString()); // "Hi there"

免费的 ASCII 艺术:

                  +--------------------+
    buf1--------->|                    |
                  | === The Object === |
                  |                    |
    buf2--------->|    Data:           |
                  |      * foo = "bar" |
                  |      * x = 27      |   
                  |                    |
                  +--------------------+

另一种理解方式是 JVM 有一个所有对象的主列表,由 ID 索引。我们创建一个对象 (buf1 = new StringBuffer();),JVM 为该对象分配 ID 42 并将该 ID 存储在 buf1 中。每当我们使用 buf1 时,JVM 都会从中获取值 42 并在其主列表中查找对象,然后使用该对象。当我们执行 buf2 = buf1; 时,变量 buf2 得到值 42 的副本,所以当我们使用 buf2,JVM 看到对象引用 #42 并使用相同的对象。这不是字面上的解释(尽管从平流层的角度来看,如果您将“JVM”理解为“JVM 和内存管理器和操作系统”,这不是一百万英里),但有助于思考对象引用实际上是什么。

在该背景下,您可以看到 toCommand 如何获取 reference(42 或其他),而不是实际的 StringBuffer 对象数据。因此对它的操作在主列表中查找它并改变它的状态(因为它保存状态信息并允许我们改变它)。调用者看到对象状态的变化,因为对象 保存状态,引用只是指向对象。

Either way... it should be considered a bad practice to write code like this in Java, right?

一点也不,这是正常的做法。如果不这样做,将很难使用 Java(或大多数其他 OOP 语言)。与 intlong 等基本类型相比,对象很大,因此移动它们的成本很高;对象引用是基元的大小,因此它们很容易传递。此外,拥有事物的副本会使系统的各个部分难以交互。拥有对共享对象的引用使其变得非常容易。

关于java - 更改 Java 中传递的参数(通过 ref、value 调用),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3165358/

相关文章:

java - 马文 : Where be the code?

java - 如何使用Java上传图像Url上传到Fire Storage并同时将其保存在fireStore中

java - 在 Java 中将信息从一个端口传递到另一个端口

c++ - 通过 "pass by value"将一个函数传递给另一个函数

arrays - 绕过字符串数组作为参数并在 PostgreSQL 中使用动态查询

java - 将 Class 对象传递给方法

php - 在php中将隐藏字段中的值从一个页面传递到另一个页面

java - 在 SVG 中创建图像并使用 Base64 编码 URI 和 JAVA 在 HTML 中渲染它们

c++ - 将二维数组指针参数分配给局部数组指针变量

java - 如何使用 Math.random 将值放置在数组中的随机位置?