我一直以为Java使用pass-by-reference. 但是,我读了一篇博客文章,声称Java使用pass-by-value. 我不认为我明白作者所做的区别。
什么是解释?
我一直以为Java使用pass-by-reference. 但是,我读了一篇博客文章,声称Java使用pass-by-value. 我不认为我明白作者所做的区别。
什么是解释?
当前回答
只需显示对比,请比较以下 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 只有兩種通過: 根據內置類型的價值,並根據對象類型的指標的價值。
其他回答
这是一个非常简单的方式来理解这一点. 让我们通过C++参考。
#include <iostream>
using namespace std;
class Foo {
private:
int x;
public:
Foo(int val) {x = val;}
void foo()
{
cout<<x<<endl;
}
};
void bar(Foo& ref)
{
ref.foo();
ref = *(new Foo(99));
ref.foo();
}
int main()
{
Foo f = Foo(1);
f.foo();
bar(f);
f.foo();
return 0;
}
什么是结果?
1 1 99 99
因此,在 bar() 将新值分配到输入的“参考”后,它实际上改变了从主要本身输入的值,解释了从主要打印99 的最后一个 f.foo() 呼叫。
现在,让我们看看Java说了什么。
public class Ref {
private static class Foo {
private int x;
private Foo(int x) {
this.x = x;
}
private void foo() {
System.out.println(x);
}
}
private static void bar(Foo f) {
f.foo();
f = new Foo(99);
f.foo();
}
public static void main(String[] args) {
Foo f = new Foo(1);
System.out.println(f.x);
bar(f);
System.out.println(f.x);
}
}
它说:
1 1 99 1
因此,Foo的主要引用被转移到酒吧,仍然没有改变!
这个例子清楚地表明,Java不是与C++相同的,当我们说“通过参考”。基本上,Java将“参考”作为“值”转移到功能,这意味着Java通过值。
与某些其他语言不同,Java不允许您在 pass-by-value 和 pass-by-reference 之间选择。
所有论点都以价值为准。
一个方法通话可以通过两个类型的 valuesto 一个方法
原始值的副本(例如,类型值 int 和双值)对物体的参考副本。
当一个方法改变原始类型参数时,参数的变化不会影响呼叫方法的原始论点值。
如果你修改一个参考类型参数以便它指向另一个对象,只有参数指向新对象 - 呼叫器的变量中存储的参数仍然指向原始对象。
参考: JavaTM 如何编程(早期对象),第十版
Java 编程语言仅通过值的论点,也就是说,您无法从所称方法中更改呼叫方法中的论点值。
但是,当一个对象例子作为论点转移到一种方法时,论点的价值不是对象本身,而是对象的参考。
对于许多人来说,这似乎是通过参考,行为上,它与通过参考有很多共同点,但是,有两个原因,这是不准确的。
第一,改变已转化为一种方法的能力仅适用于对象,而不是原始价值;第二,与对象类型变量相关的实际价值是对象的参考,而不是对象本身。
The following code example illustrates this point:
1 public class PassTest {
2
3 // Methods to change the current values
4 public static void changeInt(int value) {
5 value = 55;
6 }
7 public static void changeObjectRef(MyDate ref) {
8 ref = new MyDate(1, 1, 2000);
9 }
10 public static void changeObjectAttr(MyDate ref) {
11 ref.setDay(4);
12 }
13
14 public static void main(String args[]) {
15 MyDate date;
16 int val;
17
18 // Assign the int
19 val = 11;
20 // Try to change it
21 changeInt(val);
22 // What is the current value?
23 System.out.println("Int value is: " + val);
24
25 // Assign the date
26 date = new MyDate(22, 7, 1964);
27 // Try to change it
28 changeObjectRef(date);
29 // What is the current value?
30 System.out.println("MyDate: " + date);
31
32 // Now change the day attribute
33 // through the object reference
34 changeObjectAttr(date);
35 // What is the current value?
36 System.out.println("MyDate: " + date);
37 }
38 }
This code outputs the following:
java PassTest
Int value is: 11
MyDate: 22-7-1964
MyDate: 4-7-1964
The MyDate object is not changed by the changeObjectRef method;
however, the changeObjectAttr method changes the day attribute of the
MyDate object.
不要重复,但对于那些在阅读许多答案后仍然可能会感到困惑的人来说,有一点:
通过值在Java是不等于通过值在C++,虽然听起来像这样,这可能是为什么有混乱。
打破它:
通过值在 C++ 意味着通过对象的值(如果对象),字面上,对象的副本通过值在 Java 意味着通过对象的地址值(如果对象),而不是真正的对象的“值”(一个副本)如 C++ 通过值在 Java,在一个对象(例如 myObj.setName(“新”)在一个函数内运作的对象(例如 myObj.setName(“新”)在函数之外对对象产生影响;通过通过函数的值。
所以,朋友们,一切都只是关于术语定义的差异(通过语言),你只需要知道它是如何工作的(也许有时有点混淆它是如何称之为我承认)!
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 |
+---+