我一直以为Java使用pass-by-reference. 但是,我读了一篇博客文章,声称Java使用pass-by-value. 我不认为我明白作者所做的区别。
什么是解释?
我一直以为Java使用pass-by-reference. 但是,我读了一篇博客文章,声称Java使用pass-by-value. 我不认为我明白作者所做的区别。
什么是解释?
当前回答
Java 总是通过值,而不是通过参考。
Pass by reference(也称为 pass by address)是指实际参数地址的副本存储。
public class PassByValue {
public static void main(String[] args) {
Test t = new Test();
t.name = "initialvalue";
new PassByValue().changeValue(t);
System.out.println(t.name);
}
public void changeValue(Test f) {
f.name = "changevalue";
}
}
class Test {
String name;
}
让我们一步一步了解一下:
Test t = new Test();
正如我们都知道,它将创建一个对象,并将参考值返回t 例如,假设t 的值为 0x100234 (我们不知道实际的 JVM 内部值,这只是一个例子) 。
此分類上一篇
new PassByValue().changeValue(t);
通过 t 函数时,它不会直接通过对象测试的实际参考值,但它会创建 t 的副本,然后将其转移到函数。 因为它通过值,它会通过变量的副本而不是实际的参考值。 因为我们说 t 的值是 0x100234, t 和 f 都将具有相同的值,因此它们将指向相同的 ob。
此分類上一篇
public class PassByValue {
public static void main(String[] args) {
Test t = new Test();
t.name = "initialvalue";
new PassByValue().changeRefence(t);
System.out.println(t.name);
}
public void changeRefence(Test f) {
f = null;
}
}
class Test {
String name;
}
这会扔一个NullPointerException吗? 不,因为它只通过一个副本的参考。 在通过参考的情况下,它可能会扔一个NullPointerException,如下所示:
此分類上一篇
希望这能帮助。
其他回答
只需显示对比,请比较以下 C++ 和 Java 剪辑:
在 C++ 中: 注意: 坏代码 - 记忆泄漏! 但它证明了这一点。
void cppMethod(int val, int &ref, Dog obj, Dog &objRef, Dog *objPtr, Dog *&objPtrRef)
{
val = 7; // Modifies the copy
ref = 7; // Modifies the original variable
obj.SetName("obj"); // Modifies the copy of Dog passed
objRef.SetName("objRef"); // Modifies the original Dog passed
objPtr->SetName("objPtr"); // Modifies the original Dog pointed to
// by the copy of the pointer passed.
objPtr = new Dog("newObjPtr"); // Modifies the copy of the pointer,
// leaving the original object alone.
objPtrRef->SetName("objRefPtr"); // Modifies the original Dog pointed to
// by the original pointer passed.
objPtrRef = new Dog("newObjPtrRef"); // Modifies the original pointer passed
}
int main()
{
int a = 0;
int b = 0;
Dog d0 = Dog("d0");
Dog d1 = Dog("d1");
Dog *d2 = new Dog("d2");
Dog *d3 = new Dog("d3");
cppMethod(a, b, d0, d1, d2, d3);
// a is still set to 0
// b is now set to 7
// d0 still have name "d0"
// d1 now has name "objRef"
// d2 now has name "objPtr"
// d3 now has name "newObjPtrRef"
}
在Java,
public static void javaMethod(int val, Dog objPtr)
{
val = 7; // Modifies the copy
objPtr.SetName("objPtr") // Modifies the original Dog pointed to
// by the copy of the pointer passed.
objPtr = new Dog("newObjPtr"); // Modifies the copy of the pointer,
// leaving the original object alone.
}
public static void main()
{
int a = 0;
Dog d0 = new Dog("d0");
javaMethod(a, d0);
// a is still set to 0
// d0 now has name "objPtr"
}
Java 只有兩種通過: 根據內置類型的價值,並根據對象類型的指標的價值。
Java 以值复制参考,因此,如果您将其更改为另一个(例如,使用新)则参考不会在方法之外更改。
Java 总是通过值的论点,而不是参考。
让我们用一个例子来解释这一点:
public class Main {
public static void main(String[] args) {
Foo f = new Foo("f");
changeReference(f); // It won't change the reference!
modifyReference(f); // It will modify the object that the reference variable "f" refers to!
}
public static void changeReference(Foo a) {
Foo b = new Foo("b");
a = b;
}
public static void modifyReference(Foo c) {
c.setAttribute("c");
}
}
我将在步骤中解释这一点:
宣布一个参考名为Foo类型,并将其分配给一个新的Foo类型对象与属性“f”。Foo f =新Foo(“f”);从方法侧,一个Foo类型的参考名称A被宣布,它最初被分配为零。
我希望你现在明白如何通过对象作为论点在Java工作:)
区别,或可能只是我记得我曾经像原始海报一样的印象是这样的:Java总是通过价值,Java中的所有对象(除了原始对象)都是参考。
例如,使用 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 复制并通过参考值,而不是对象. 因此,方法操作将改变对象,因为参考指向原始对象. 但是,因为参考是复制,交换将失败。 方法参考交换,但不是原始参考。 不幸的是,在一个方法呼叫后,你只剩下未交换的原始参考。