我一直以为Java使用pass-by-reference. 但是,我读了一篇博客文章,声称Java使用pass-by-value. 我不认为我明白作者所做的区别。
什么是解释?
我一直以为Java使用pass-by-reference. 但是,我读了一篇博客文章,声称Java使用pass-by-value. 我不认为我明白作者所做的区别。
什么是解释?
当前回答
Java 使用 pass-by-value,但效果不同的是你是否使用原始或参考类型。
当你将原始类型作为论点转移到一种方法时,它将获得原始类型的副本,而方法块内的任何变化都不会改变原始变量。
当您将参考类型作为一个论点转移到一个方法时,它仍然得到一个副本,但它是对对象的参考的副本(换句话说,您正在获得记忆地址的副本在对象所在地),因此对象中的任何变化在方法的区块内将影响原始对象在区块外。
其他回答
例如,使用 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 总是通过价值,没有例外,永远。
因此,怎样才能让任何人完全困惑,相信Java是通过参考,或者认为他们有一个Java作为通过参考的例子?关键点是Java从来没有提供直接访问对象本身的价值,在任何情况下。
因此,当呼叫一种方法时
对于原始论点(int、long等)而言,值的过渡是原始的实际价值(例如,3)。
所以,如果你有DoSomething(foo)和公共空白DoSomething(Foo foo) {.. } 两个 Foos 有复制的参考,指向相同的对象。
当然,通过值对一个对象的参考看起来非常相似(并且在实践中不可分辨的)通过对象的参考。
Java 按值传输参考。
因此,你不能改变通过的参考。
讓我試圖用四個例子來解釋我的理解: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 始终是 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());
}
}