Java函数调用。非平凡对象是否通过引用复制?
几周前我开始使用java。在此之前,我曾在嵌入式目标上与c/c++合作多年,在Win PC上与c#一起使用UI 我得到了一个非常简单的例子:Java函数调用。非平凡对象是否通过引用复制?,java,Java,几周前我开始使用java。在此之前,我曾在嵌入式目标上与c/c++合作多年,在Win PC上与c#一起使用UI 我得到了一个非常简单的例子: public class StreamProcessing { public static void main(String[] args) { Stream stream = new Stream(); //after this line: Stream string empty StreamFiller.fi
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);
}
}
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);
}
}
我希望无论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;
}
}
如果我错了,请纠正我,但是由于字符串类的实际文本是在堆上分配的,StreamProcessing()流对象和fillStream()的(假定复制的)本地对象都指向堆上的同一地址(是的,我现在不是像c/c++中那样的实际内存地址,而是某个唯一的对象标识符)
那么我的假设正确吗?非平凡对象(即堆上分配的对象)是通过引用传递的吗
thx为您提供帮助:)即使在Java中,所有内容都是按值传递的,但基本数据类型(如int、char和boolean)和引用数据类型传递给方法的方式也存在差异。 传递基元数据类型的值时,只能在特定方法的范围内更改此值。传递引用数据类型的值时,引用将保持不变,但值将全局更改(或在初始化对象的任何范围内更改)
也请参阅更多信息:
< P> java语言不允许您在代码中堆/栈区分C和C++做的方式。 相反,它将所有数据类型分为两组:这些是简单的内置数字类型,如
int
、double
或boolean
(在Java中不是数字类型)。请注意,
String
不是这种类型如果它是一个类,那么它就是一个对象类型。这适用于内置类型,如
String
,以及用户定义的类型,如流
类。对于这些类型,无论您查看的是局部变量、类成员、实例成员还是函数参数,都只能看到一个引用
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);
}
}
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++中,行<代码> VAR2= VAR1;
会调用一个复制构造函数并创建一个新对象,但在Java中没有这样的东西。如果需要副本,则需要显式调用clone
方法
保存在var1
中并复制到var2
的内容只是一个参考。
所以两个变量“指向”同一个对象
再说一遍,这个类是否微不足道并不重要。即使一个类是完全空的,您仍然只会得到一个对这个类的任何对象的引用
至于前面提到的基本类型,Java为它们提供了Integer
和Boolean
等包装类。
你可能想了解一下
还有一点需要注意的是,某些类型是不可变的——也就是说,它们不提供在创建数据后更改数据的方法
String
在Java中是一种不可变的类型,但它与任何其他类型也有点不同。
它有特权。
虽然java不支持C++之类的操作符重载,但是对于String 类型,语言确实提供了一个特殊的<代码> +操作符<代码>预处理字符串连接。
然而,由于String
对象是不可变的,因此任何串联操作都将创建一个全新的String
对象,即使是这样的对象:
String a = "Hello";
a = a + " world!";
这将创建一个新字符串“Hello world”,并将对它的引用存储在a
中,使对旧“Hello”字符串的引用在将来某个时候被垃圾收集。在Java中,对象总是按引用传递,只有像int
这样的原语才按值传递。堆或堆栈并不重要。这在SO和web上都是重复的。通过值传递引用;没有复制。可能是复制的