我一直以为Java使用pass-by-reference. 但是,我读了一篇博客文章,声称Java使用pass-by-value. 我不认为我明白作者所做的区别。
什么是解释?
我一直以为Java使用pass-by-reference. 但是,我读了一篇博客文章,声称Java使用pass-by-value. 我不认为我明白作者所做的区别。
什么是解释?
当前回答
Java 通过原始类型为值和类型为参考
现在,人们喜欢无限地争论是否“通过参考”是正确的方式来描述Java et al. 实际上做什么。
通过一个对象不会复制对象,转移到函数的对象可以由函数修改其成员,转移到函数的原始值不能由函数修改。
在我的书中,它被称为通过参考。
布莱恩·比(Brian Bi) - 哪种编程语言通过参考?
其他回答
例如,使用 badSwap() 方法:
public void badSwap(int var1, int var2)
{
int temp = var1;
var1 = var2;
var2 = temp;
}
当 badSwap() 返回时,作为论点过渡的变量将仍然保持其原始值。 该方法也会失败,如果我们将论点类型从 int 转换为 对象,因为 Java 通过对象参考值也。
public void tricky(Point arg1, Point arg2)
{
arg1.x = 100;
arg1.y = 100;
Point temp = arg1;
arg1 = arg2;
arg2 = temp;
}
public static void main(String [] args)
{
Point pnt1 = new Point(0,0);
Point pnt2 = new Point(0,0);
System.out.println("X: " + pnt1.x + " Y: " +pnt1.y);
System.out.println("X: " + pnt2.x + " Y: " +pnt2.y);
System.out.println(" ");
tricky(pnt1,pnt2);
System.out.println("X: " + pnt1.x + " Y:" + pnt1.y);
System.out.println("X: " + pnt2.x + " Y: " +pnt2.y);
}
如果我们执行这个主要()方法,我们会看到以下输出:
X: 0 Y: 0
X: 0 Y: 0
X: 100 Y: 100
X: 0 Y: 0
图1 转移到一个方法后,对象将至少有两种参考。
Java 复制并通过参考值,而不是对象. 因此,方法操作将改变对象,因为参考指向原始对象. 但是,因为参考是复制,交换将失败。 方法参考交换,但不是原始参考。 不幸的是,在一个方法呼叫后,你只剩下未交换的原始参考。
与某些其他语言不同,Java不允许您在 pass-by-value 和 pass-by-reference 之间选择。
所有论点都以价值为准。
一个方法通话可以通过两个类型的 valuesto 一个方法
原始值的副本(例如,类型值 int 和双值)对物体的参考副本。
当一个方法改变原始类型参数时,参数的变化不会影响呼叫方法的原始论点值。
如果你修改一个参考类型参数以便它指向另一个对象,只有参数指向新对象 - 呼叫器的变量中存储的参数仍然指向原始对象。
参考: JavaTM 如何编程(早期对象),第十版
在Java中,方法论都是通过价值的:
Java 论点都是通过值(当使用方法时,值或参考复制):
在原始类型的情况下,Java行为是简单的:值复制到原始类型的另一个例子。
行为可能与原始类型不同:因为复制的对象变量包含相同的地址(到相同的对象)。对象的内容/会员可能仍然在一个方法内进行修改,然后在外部访问,给出幻觉(包含)对象本身通过参考。
“紧张”对象似乎是城市传说说“对象通过参考”的好对例子:
A String Object,持有字符的序列宣布最终不能修改. 只有对象的地址可以用另一个使用“新”。 使用“新”更新变量,不会让对象从外部访问,因为变量最初通过值并复制。
Pass By Reference 收到的函数值是通话者所使用的对象的参考。 通话者所指的对象的任何函数都将被通话者看到,并将从那时起与这些变化进行操作。
正如这些定义所表明的那样,参考通过值是毫无意义的,如果我们要接受这个定义,那么这些术语就变得毫无意义,所有语言都只是通过值。
因此,有了这个理解,我们可以看看Java,并看到它实际上有两种。所有Java原始类型总是通过值,因为你收到一个复印件的呼叫器的对象,并且不能修改他们的复印件。
首先,我们应该明白什么是通过值或通过参考的意思。
通过值:方法参数值复制到另一个变量,然后复制的对象通过,这就是为什么它被称为通过值。
public class Balloon {
private String color;
public Balloon(){}
public Balloon(String c){
this.color=c;
}
public String getColor() {
return color;
}
public void setColor(String color) {
this.color = color;
}
}
public class Test {
public static void main(String[] args) {
Balloon red = new Balloon("Red"); //memory reference 50
Balloon blue = new Balloon("Blue"); //memory reference 100
swap(red, blue);
System.out.println("red color="+red.getColor());
System.out.println("blue color="+blue.getColor());
foo(blue);
System.out.println("blue color="+blue.getColor());
}
private static void foo(Balloon balloon) { //baloon=100
balloon.setColor("Red"); //baloon=100
balloon = new Balloon("Green"); //baloon=200
balloon.setColor("Blue"); //baloon = 200
}
//Generic swap method
public static void swap(Object o1, Object o2){
Object temp = o1;
o1=o2;
o2=temp;
}
}
当我们执行上述程序时,我们会跟踪输出。
red color=Red
blue color=Blue
blue color=Red
Balloon red = new Balloon("Red");
Balloon blue = new Balloon("Blue");
public static void swap(Object o1, Object o2){ //o1=50, o2=100
Object temp = o1; //temp=50, o1=50, o2=100
o1=o2; //temp=50, o1=100, o2=100
o2=temp; //temp=50, o1=100, o2=50
} //method terminated
如果你已经明白了这一点,你可以轻松地理解混乱的原因. 因为变量只是对物体的参考,我们会感到困惑,我们正在通过参考,所以Java通过参考。
现在,让我们分析 foo() 方法执行。
private static void foo(Balloon balloon) { //baloon=100
balloon.setColor("Red"); //baloon=100
balloon = new Balloon("Green"); //baloon=200
balloon.setColor("Blue"); //baloon = 200
}
第一行是最重要的,当我们称之为一个方法时,该方法在参考位置上被称为对象,在这一点上,气球指向100,因此它的颜色变成红色。