- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
几周前我开始接触 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++ 那样在代码中区分堆/堆栈。
相反,它将所有数据类型分为两组:
基本类型:
这些是简单的内置数字类型,例如 int
、double
或 boolean
(不是 Java 中的数字类型)。
请注意,String
不是这样的类型!
对象类型:
如果它是一个类,那么它就是一个对象类型。这适用于内置类型(例如 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/
我是一名优秀的程序员,十分优秀!