我一直以为Java使用pass-by-reference. 但是,我读了一篇博客文章,声称Java使用pass-by-value. 我不认为我明白作者所做的区别。
什么是解释?
我一直以为Java使用pass-by-reference. 但是,我读了一篇博客文章,声称Java使用pass-by-value. 我不认为我明白作者所做的区别。
什么是解释?
当前回答
讓我試圖用四個例子來解釋我的理解:Java是通過價值,而不是通過参考。
* * *
◎
public class PassByValueString {
public static void main(String[] args) {
new PassByValueString().caller();
}
public void caller() {
String value = "Nikhil";
boolean valueflag = false;
String output = method(value, valueflag);
/*
* 'output' is insignificant in this example. we are more interested in
* 'value' and 'valueflag'
*/
System.out.println("output : " + output);
System.out.println("value : " + value);
System.out.println("valueflag : " + valueflag);
}
public String method(String value, boolean valueflag) {
value = "Anand";
valueflag = true;
return "output";
}
}
output : output
value : Nikhil
valueflag : false
例子2:
/** * * Pass By 價值 */
public class PassByValueNewString {
public static void main(String[] args) {
new PassByValueNewString().caller();
}
public void caller() {
String value = new String("Nikhil");
boolean valueflag = false;
String output = method(value, valueflag);
/*
* 'output' is insignificant in this example. we are more interested in
* 'value' and 'valueflag'
*/
System.out.println("output : " + output);
System.out.println("value : " + value);
System.out.println("valueflag : " + valueflag);
}
public String method(String value, boolean valueflag) {
value = "Anand";
valueflag = true;
return "output";
}
}
output : output
value : Nikhil
valueflag : false
/** 这个“通过价值”具有“通过参考”的感觉
但是,从这个例子,我们可以理解,它只是通过值,记住,在这里我们通过参考作为值. 也就是说:参考通过值. 这就是为什么它们可以改变,但它仍然保持在当地范围后真实。
public class PassByValueObjectCase1 {
private class Student {
int id;
String name;
public Student() {
}
public Student(int id, String name) {
super();
this.id = id;
this.name = name;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "Student [id=" + id + ", name=" + name + "]";
}
}
public static void main(String[] args) {
new PassByValueObjectCase1().caller();
}
public void caller() {
Student student = new Student(10, "Nikhil");
String output = method(student);
/*
* 'output' is insignificant in this example. we are more interested in
* 'student'
*/
System.out.println("output : " + output);
System.out.println("student : " + student);
}
public String method(Student student) {
student.setName("Anand");
return "output";
}
}
结果
output : output
student : Student [id=10, name=Anand]
例子4:
* * *
除了在Example3(PassByValueObjectCase1.java)中提到的外,我们不能在原始范围之外更改实际参考。
注意: 我不符合私人课堂学生的代码. 学生的课堂定义与例子3相同。
◎
public class PassByValueObjectCase2 {
public static void main(String[] args) {
new PassByValueObjectCase2().caller();
}
public void caller() {
// student has the actual reference to a Student object created
// can we change this actual reference outside the local scope? Let's see
Student student = new Student(10, "Nikhil");
String output = method(student);
/*
* 'output' is insignificant in this example. we are more interested in
* 'student'
*/
System.out.println("output : " + output);
System.out.println("student : " + student); // Will it print Nikhil or Anand?
}
public String method(Student student) {
student = new Student(20, "Anand");
return "output";
}
}
output : output
student : Student [id=10, name=Nikhil]
其他回答
正如许多人之前提到的那样,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 的参考将仅在本地范围内变化,而不是在该方法之外。
真的很简单,真的很简单:
对于原始类型的变量(如 int、boolean、char 等),当您使用其名称为方法论时,您将其中的值(5、 true、c)传输。
对于参考类型的变量(例如,线条,对象等),当您使用其名称为方法论时,您将其中的值转移(对象“点”的参考值)。这个参考值被“复制”,而变量在方法引用后仍然保持其值。
不管怎样,你总是通过价值的东西。
比较这个说 C++ 你可以有一个方法来采取一个 int& 或在 C# 你可以采取一个 ref int (虽然,在这种情况下,你也必须使用 ref 修改器,当将变量的名称转移到方法。
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,如下所示:
此分類上一篇
希望这能帮助。
Java 仅通过值,没有通过参考,例如,您可以看到下面的示例。
package com.asok.cop.example.task;
public class Example {
int data = 50;
void change(int data) {
data = data + 100;// changes will be in the local variable
System.out.println("after add " + data);
}
public static void main(String args[]) {
Example op = new Example();
System.out.println("before change " + op.data);
op.change(500);
System.out.println("after change " + op.data);
}
}
出口:
before change 50
after add 600
after change 50
正如迈克尔在评论中所说:
物品仍然通过价值,尽管它们的操作表现像通过参考。 考虑无变 人物(人){人 = 新人(); } 呼叫者对个人对象的参考将保持不变. 物品本身通过价值,但其成员可以受到变化的影响。 为了成为真实的通过参考,我们必须能够重新分配论点到一个
Java 总是通过价值,没有例外,永远。
因此,怎样才能让任何人完全困惑,相信Java是通过参考,或者认为他们有一个Java作为通过参考的例子?关键点是Java从来没有提供直接访问对象本身的价值,在任何情况下。
因此,当呼叫一种方法时
对于原始论点(int、long等)而言,值的过渡是原始的实际价值(例如,3)。
所以,如果你有DoSomething(foo)和公共空白DoSomething(Foo foo) {.. } 两个 Foos 有复制的参考,指向相同的对象。
当然,通过值对一个对象的参考看起来非常相似(并且在实践中不可分辨的)通过对象的参考。