我一直以为Java使用pass-by-reference. 但是,我读了一篇博客文章,声称Java使用pass-by-value. 我不认为我明白作者所做的区别。
什么是解释?
我一直以为Java使用pass-by-reference. 但是,我读了一篇博客文章,声称Java使用pass-by-value. 我不认为我明白作者所做的区别。
什么是解释?
当前回答
原始和对象参考,但对象可以改变,如果它们的界面允许。
当您将对象转移到一个方法时,您正在转移一个参考,并且该对象可以通过方法实施进行修改。
void bithday(Person p) {
p.age++;
}
对象本身的参考,通过值:你可以重新分配参数,但变化不会反映:
void renameToJon(Person p) {
p = new Person("Jon"); // this will not work
}
jack = new Person("Jack");
renameToJon(jack);
sysout(jack); // jack is unchanged
作为效应问题,“p”是参考(对象的指标),不能改变。
原始类型通过值,对象的参考也可以被视为原始类型。
为了回报,一切都通过了价值。
其他回答
短篇小说:
非原始:Java通过参考值;原始:仅值。
结局。
现在,如果你想想想什么(1)意味着,想象你有一个类的苹果:
class Apple {
private double weight;
public Apple(double weight) {
this.weight = weight;
}
// getters and setters ...
}
然后,当你将这个类的一个例子转移到主要方法:
class Main {
public static void main(String[] args) {
Apple apple = new Apple(3.14);
transmogrify(apple);
System.out.println(apple.getWeight()+ " the goose drank wine...";
}
private static void transmogrify(Apple apple) {
// does something with apple ...
apple.setWeight(apple.getWeight()+0.55);
}
}
哦......但你可能知道这一点,你对当你做这样的事情时会发生什么感兴趣:
class Main {
public static void main(String[] args) {
Apple apple = new Apple(3.14);
transmogrify(apple);
System.out.println("Who ate my: "+apple.getWeight()); // will it still be 3.14?
}
private static void transmogrify(Apple apple) {
// assign a new apple to the reference passed...
apple = new Apple(2.71);
}
}
Java 通过值的参数,但对于对象变量,值基本上是对象的参考。
public static void dummyIncrease(int[] x, int y)
{
x[0]++;
y++;
}
public static void main(String[] args)
{
int[] arr = {3, 4, 5};
int b = 1;
dummyIncrease(arr, b);
// arr[0] is 4, but b is still 1
}
main()
arr +---+ +---+---+---+
| # | ----> | 3 | 4 | 5 |
+---+ +---+---+---+
b +---+ ^
| 1 | |
+---+ |
|
dummyIncrease() |
x +---+ |
| # | ------------+
+---+
y +---+
| 1 |
+---+
我看到所有的答案都是相同的:通过值。 然而,最近的布莱恩·戈茨关于Valhalla项目的更新实际上会以不同的方式回答:
事实上,这是一个常见的“gotcha”问题,关于Java对象是否通过值或参考,答案是“也不”:对象参考通过值。
您可以在这里阅读更多: 瓦尔哈拉州 部分 2: 语言模型
编辑:Brian Goetz是Java语言建筑师,领导项目如Project Valhalla和Project Amber。
Edit-2020-12-08: 瓦尔哈拉的最新状态
将变量转换为方法(目标 7.3) 7.3 确定对对象参考和原始值的影响,当它们转换为对参数进行任务或其他修改操作的方法时。
1. import java.awt.Dimension;
2. class ReferenceTest {
3. public static void main (String [] args) {
4. Dimension d = new Dimension(5,10);
5. ReferenceTest rt = new ReferenceTest();
6. System.out.println("Before modify() d.height = " + d.height);
7. rt.modify(d);
8. System.out.println("After modify() d.height = "
9. }
10.
11.
12.
13. }
14. }
C:\Java Projects\Reference>java ReferenceTest Before modify() d.height = 10 dim = 11 After modify() d.height = 11
注意,当第 4 行的尺寸对象转移到修改() 方法时,在该方法中发生的对象的任何变化都会转移到该对象的参考转移。在前面的例子中,参考变量 d 和 dim 都指向相同的对象。
void bar() {
Foo f = new Foo();
doStuff(f);
}
void doStuff(Foo g) {
g.setName("Boo");
g = new Foo();
}
class ReferenceTest {
public static void main (String [] args) {
int a = 1;
ReferenceTest rt = new ReferenceTest();
System.out.println("Before modify() a = " + a);
rt.modify(a);
System.out.println("After modify() a = " + a);
}
void modify(int number) {
number = number + 1;
System.out.println("number = " + number);
}
}
Before modify() a = 1
number = 2
After modify() a = 1
Java 是由價值通過的。
在某种程度上,我从来没有透露过原始数据类型和对象的值/参考。因此,我用下列代码来测试我的满意度和清晰度;可能有助于寻求类似清晰度的人:
class Test {
public static void main (String[] args) throws java.lang.Exception
{
// Primitive type
System.out.println("Primitve:");
int a = 5;
primitiveFunc(a);
System.out.println("Three: " + a); //5
//Object
System.out.println("Object:");
DummyObject dummyObject = new DummyObject();
System.out.println("One: " + dummyObject.getObj()); //555
objectFunc(dummyObject);
System.out.println("Four: " + dummyObject.getObj()); //666 (555 if line in method uncommented.)
}
private static void primitiveFunc(int b) {
System.out.println("One: " + b); //5
b = 10;
System.out.println("Two:" + b); //10
}
private static void objectFunc(DummyObject b) {
System.out.println("Two: " + b.getObj()); //555
//b = new DummyObject();
b.setObj(666);
System.out.println("Three:" + b.getObj()); //666
}
}
class DummyObject {
private int obj = 555;
public int getObj() { return obj; }
public void setObj(int num) { obj = num; }
}
如果行 b = 新 DummyObject() 没有评论,随后进行的修改是在一个新的对象,一个新的实例上进行的。 因此,它不反映在方法被召回的地方。 但是,否则,变化是反映的,因为修改只是在对象的“参考”上进行的,即 - b 点到相同的 dummyObject。
在这个条纹中的答案之一(https://stackoverflow.com/a/12429953/4233180)的描述可以帮助获得更深入的理解。