我一直以为Java使用pass-by-reference. 但是,我读了一篇博客文章,声称Java使用pass-by-value. 我不认为我明白作者所做的区别。
什么是解释?
我一直以为Java使用pass-by-reference. 但是,我读了一篇博客文章,声称Java使用pass-by-value. 我不认为我明白作者所做的区别。
什么是解释?
当前回答
首先,我们应该明白什么是通过值或通过参考的意思。
通过值:方法参数值复制到另一个变量,然后复制的对象通过,这就是为什么它被称为通过值。
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,因此它的颜色变成红色。
其他回答
例如,使用 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,参数是经过的变量的副本,所有对象都是用参考来定义的,参考是存储一个记忆地址的变量,其中对象在记忆中。
查看评论以了解执行中发生了什么;跟随数字,因为它们显示执行的流动。
class Example
{
public static void test (Cat ref)
{
// 3 - <ref> is a copy of the reference <a>
// both currently reference Grumpy
System.out.println(ref.getName());
// 4 - now <ref> references a new <Cat> object named "Nyan"
ref = new Cat("Nyan");
// 5 - this should print "Nyan"
System.out.println( ref.getName() );
}
public static void main (String [] args)
{
// 1 - a is a <Cat> reference that references a Cat object in memory with name "Grumpy"
Cat a = new Cat("Grumpy");
// 2 - call to function test which takes a <Cat> reference
test (a);
// 6 - function call ends, and <ref> life-time ends
// "Nyan" object has no references and the Garbage
// Collector will remove it from memory when invoked
// 7 - this should print "Grumpy"
System.out.println(a.getName());
}
}
Java 以價值通過一切!!!
创建一个对象,通过一个名字和年龄:
PersonClass variable1 = new PersonClass("Mary", 32);
PersonClass variable2;
// 变量2 和变量1 现在提到相同的对象
variable2 = variable1;
PersonClass variable3 = new PersonClass("Andre", 45);
// variable1 现在指向 variable3
variable1 = variable3;
什么是由此产生的?
System.out.println(variable2);
System.out.println(variable1);
Mary 32
Andre 45
如果你能理解这个例子,我们做了,否则,请访问这个网页详细解释:
网页
正如许多人之前提到的那样,Java总是有价值的。
下面是另一个例子,这将帮助你理解差异(经典交换例子):
public class Test {
public static void main(String[] args) {
Integer a = new Integer(2);
Integer b = new Integer(3);
System.out.println("Before: a = " + a + ", b = " + b);
swap(a,b);
System.out.println("After: a = " + a + ", b = " + b);
}
public static swap(Integer iA, Integer iB) {
Integer tmp = iA;
iA = iB;
iB = tmp;
}
}
印刷:
前: a = 2, b = 3 后: a = 2, b = 3
这是因为 iA 和 iB 是新的本地参考变量,具有相同值的过去参考(他们的点到 a 和 b 相应)。因此,试图改变 iA 或 iB 的参考将仅在本地范围内变化,而不是在该方法之外。
主要的角石知识必须是引用的一个,
当对象引用转移到一种方法时,引用本身通过使用呼叫值。 但是,因为引用的值是指对象,则该值的副本仍然是指其相应论点所引用的相同对象。
Java: A Beginner's Guide 第六版 希尔伯特·希尔德