gpt4 book ai didi

Java 函数调用。非平凡对象是否通过引用复制?

转载 作者:行者123 更新时间:2023-12-01 23:42:40 25 4
gpt4 key购买 nike

几周前我开始接触 Java。在此之前,我在嵌入式目标上使用 c/c++ 工作多年,并在 Win PC 上使用带有 UI Stuff 的 c# 工作。

我得到了这个非常简单的例子:

public class StreamProcessing {

public static void main(String[] args) {
Stream stream = new Stream(); //after this line: Stream string empty

StreamFiller.fillStream(stream); //after this line: Stream string not empty any more
StreamPrinter.printStream(stream);

}

}

我希望无论 StreamFiller.fillStream() 做什么,参数都会被复制。然而,看起来 fillStream 正在修改实际的流对象本身。Stream 类基本上包含一个字符串

public class Stream {
private String content = "";
int index = 0;

public char readChar() {
if (index < content.length()) {
return content.charAt(index++);
} else {
return 0;
}
}

public void writeString(String str) {
content += str;
}
}

Streamfiller 应该修改它的流副本,而不是原始引用

public class StreamFiller {

public static void fillStream( Stream stream ) {
stream.writeString( "This is a" );
stream.writeString( " stream." );
}
}

如果我错了,请纠正我,但由于字符串类的实际文本是在堆上分配的,所以 StreamProcessing () Stream 对象和 fillStream() 的(假定复制的)本地对象都指向同一个堆上的地址(是的,我现在它不是像 c/c++ 中那样的实际内存地址,而是一些唯一的对象标识符)

那么我的假设正确吗?非平凡对象(又名在堆上分配的对象)是通过引用传递的?

感谢您的帮助:)

最佳答案

Java 语言不允许您像 C 和 C++ 那样在代码中区分堆/堆栈。

相反,它将所有数据类型分为两组:

  1. 基本类型:
    这些是简单的内置数字类型,例如 intdoubleboolean(不是 Java 中的数字类型)。
    请注意,String 不是这样的类型!

  2. 对象类型:
    如果它是一个类,那么它就是一个对象类型。这适用于内置类型(例如 String)和用户定义类型(例如 Stream 类)。
    对于这些类型,您所看到的只是引用,无论您是查看局部变量、类成员、实例成员还是函数参数。

让我们看一个简单的例子:

public class A {
public int a;

public static void main(String [] args) {
A var1 = new A();
A var2 = var1;

var1.a = 42;

System.out.println("var2.a = " + var2.a);
}
}

如果编译并运行此示例,它将打印 42。
在 C++ 中,A var2 = var1; 行将调用复制构造函数并创建一个新对象,但在 Java 中没有这样的事情。如果您想要一个副本,您需要显式调用 clone 方法。

var1 中保存并复制到 var2 的内容只是一个引用。所以两个变量“指向”同一个对象。

再说一遍 - 类(class)是否琐碎并不重要。即使一个类完全是空的,您仍然只能获得并使用对该类的任何对象的引用。

对于前面提到的基本类型,Java 为其提供了 Integer 和 Boolean 等包装类。您可能想阅读 "boxing" and "unboxing" .

还要注意的一点是,某些类型是不可变的 - 也就是说,它们不提供在创建后更改数据的方法。

Java 中的

String 是一种不可变类型,但它也与任何其他类型有所不同。
它有特殊的特权。
虽然 Java 不像 C++ 那样支持运算符重载,但对于 String 类型,该语言确实提供了一个特殊的 + 运算符 来执行字符串连接。

然而,由于 String 对象是不可变的,任何串联操作都会创建一个全新的 String 对象,甚至是这样的:

String a = "Hello";
a = a + " world!";

这会创建一个新字符串“Hello world”,并将对其的引用存储在 a 中,而对旧“Hello”字符串的引用将在将来的某个时刻被垃圾收集。

关于Java 函数调用。非平凡对象是否通过引用复制?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58252622/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com