我一直以为Java使用pass-by-reference. 但是,我读了一篇博客文章,声称Java使用pass-by-value. 我不认为我明白作者所做的区别。
什么是解释?
我一直以为Java使用pass-by-reference. 但是,我读了一篇博客文章,声称Java使用pass-by-value. 我不认为我明白作者所做的区别。
什么是解释?
当前回答
Java 以值传输对象的参考。
因此,如果对参考论点所指出的对象进行任何修改,则将反映在原始对象上。
但是,如果引用论点指向另一个对象,则原始引用将指向原始对象。
其他回答
在我所知道的范围内,Java只知道值的呼叫,这意味着对于原始数据类型,您将使用复印件工作,对于对象,您将使用对象的参考复印件工作。
public static void swap(StringBuffer s1, StringBuffer s2) {
StringBuffer temp = s1;
s1 = s2;
s2 = temp;
}
public static void main(String[] args) {
StringBuffer s1 = new StringBuffer("Hello");
StringBuffer s2 = new StringBuffer("World");
swap(s1, s2);
System.out.println(s1);
System.out.println(s2);
}
这将人口Hello World而不是World Hello,因为在交换函数中,您使用复印件,这些复印件不会对主要的参考产生影响。
public static void appendWorld(StringBuffer s1) {
s1.append(" World");
}
public static void main(String[] args) {
StringBuffer s = new StringBuffer("Hello");
appendWorld(s);
System.out.println(s);
}
如果您将 StringBuffer 更改为 String,它只会产生 Hello 因为 String 是不可变的。
public static void appendWorld(String s){
s = s+" World";
}
public static void main(String[] args) {
String s = new String("Hello");
appendWorld(s);
System.out.println(s);
}
但是,你可以为 String 做一个插槽,这将使它能够与 Strings 一起使用:
class StringWrapper {
public String value;
public StringWrapper(String value) {
this.value = value;
}
}
public static void appendWorld(StringWrapper s){
s.value = s.value +" World";
}
public static void main(String[] args) {
StringWrapper s = new StringWrapper("Hello");
appendWorld(s);
System.out.println(s.value);
}
编辑:我认为这也是使用 StringBuffer 的理由,当涉及到“添加”两个线条时,因为你可以修改原始对象,你不能用像 String 这样的不可变的对象。
Java 是严格通过价值的
在Java中,当我们做同样的事情时,我们会用手<unk>做同样的事情;因为它们不被称为指标变量(如上所述),即使我们通过参考,我们不能通过参考,因为我们不用指标变量在Java中收集。
区别,或可能只是我记得我曾经像原始海报一样的印象是这样的:Java总是通过价值,Java中的所有对象(除了原始对象)都是参考。
“pass-by-value”和“pass-by-reference”是指变量;“pass-by-value”是指变量的值转移到函数/方法;“pass-by-reference”是指该变量的参考转移到函数;“pass-by-reference”是指变量的值转移到函数;“pass-by-reference”是指变量的值转移到函数。
它如同这样:
public static void main(String[] args) {
Dog aDog = new Dog("Max");
Dog oldDog = aDog;
// we pass the object to foo
foo(aDog);
// aDog variable is still pointing to the "Max" dog when foo(...) returns
aDog.getName().equals("Max"); // true
aDog.getName().equals("Fifi"); // false
aDog == oldDog; // true
}
public static void foo(Dog d) {
d.getName().equals("Max"); // true
// change d inside of foo() to point to a new Dog instance "Fifi"
d = new Dog("Fifi");
d.getName().equals("Fifi"); // true
}
同样:
public static void main(String[] args) {
Dog aDog = new Dog("Max");
Dog oldDog = aDog;
foo(aDog);
// when foo(...) returns, the name of the dog has been changed to "Fifi"
aDog.getName().equals("Fifi"); // true
// but it is still the same dog:
aDog == oldDog; // true
}
public static void foo(Dog d) {
d.getName().equals("Max"); // true
// this changes the name of d to be "Fifi"
d.setName("Fifi");
}
有关参考通行和值通行的更多信息,请参见以下答案: https://stackoverflow.com/a/430958/6005228. 这更详细地解释了两者背后的语法和历史,并解释了为什么Java和许多其他现代语言似乎在某些情况下都会做两件事。
基本上,重新定义对象参数不会影响论点,例如,
private static void foo(Object bar) {
bar = null;
}
public static void main(String[] args) {
String baz = "Hah!";
foo(baz);
System.out.println(baz);
}
这个工作的原因是因为字符串是 baz 的值的副本,这只是“Hah!”的参考。如果它是实际的参考本身,那么 foo 会重新定义 baz 到 null。