如何将Object作为参数传递与将Array作为参数传递不同?

时间:2011-12-31 16:16:56

标签: java object arguments

我遇到过两种情况。

一个数组作为参数传递给方法,如果在被调用的方法中更新,它也会在调用方法中反映出来。

但在第二种情况下,String对象作为参数传递。该对象在被调用的方法中更新,但它不会反映在调用方法中。

我想了解两者之间的区别是什么,即使在这两种情况下,value(of reference)都作为参数传递。请参阅下面的摘录。

情景1:

class Test {
public static void main(String[] args){
int a[] = {3,4,5};
changeValue(a);
System.out.println("Value at Index 1 is "+a[1]);
}
public static void changeValue(int b[]){
b[1] = 9;
}
}

输出:

Value at Index 1 is 9

此处,与数组a相关的引用(内存地址)将传递给changeValue。因此,b只是指向与a相同的地址。 因此,无论我说b[1]还是a[1],它都指的是相同的内存地址。

情景2:

public class Test {
public static void main(String[] args){
String value = "abc";
changeValue(value);
System.out.println(value);
}
public static void changeValue(String a){
a = "xyz";
}
}

输出:

abc

如果我在此处应用相同的逻辑,则String Object VALUE的引用(Memory Address)将传递给changeValue,由a接收。 因此,现在a应该引用与VALUE相同的内存位置。因此,执行a="xyz"时,应将"abc"替换为"xyz"

有人可以指出我的理解出错了吗?在此先感谢!!

5 个答案:

答案 0 :(得分:2)

Java按值传递所有参数。这意味着生成指向String的指针的副本,然后传递给该方法。然后该方法使指针指向另一个对象,但原始指针仍然指向相同的String。

答案 1 :(得分:2)

这不是一回事:

    在第一个示例中,
  • 将数组引用作为参数传递,因此您正确地希望通过直接操作引用来更改它;
  • 但是,在第二个示例中,您传递了一个对象引用,确定 - 但您在方法中更改了引用本身。当方法返回时,a的更改不会反映出来。

考虑任何对象:

public void changeObj(Object o)
{
    o = new Whatever();
}

创建了一个新对象,但它不会在调用者中更改o。这里也是如此。

答案 2 :(得分:1)

这里的区别很简单,实际上它并不是关于字符串的不变性,因为其他一些答案(现在已编辑或删除)可能最初暗示。在一个版本中(使用字符串),您已经重新分配了引用,而在其他版本中(使用数组),您还没有。

 array[0] = foo; // sets an element, no reassignment to variable
 array = new int[] { 1,2,3 }; // assigns new array
 obj = "hey"; // assigns new value

当你重新分配变量时,你不会在方法之外观察到这种变化。更改数组的元素而不重新分配数组变量时,您将观察到这些更改。当您在对象上调用setter而不重新分配对象的实际变量时,您将观察到这些更改。当您覆盖变量(新数组,分配新值,创建新对象等)时,这些更改将被忽略。

按值传递(或复制)参数。方法内部的变量与开头外部的变量具有相同的值。变量没有链接,它们不是彼此的别名。它们碰巧包含相同的值。一旦你将值重新分配给其中一个,那就不再是真的了!外部的变量不受内部变量或甚至另一个局部变量的影响。考虑

Foo foo = new Foo();
Foo other = foo;
foo.setBar(1);
int bar = other.getBar(); // gets 1
foo = new Foo(); 
foo.setBar(42); 
int bar2 = other.getBar(); // still gets 1

fooother一段时间只引用了同一个对象。为foo分配新对象后,变量不再具有任何共同点。对于方法中的参数变量的重新分配也是如此。

答案 3 :(得分:1)

你在做不同的事情;使用您设置参数值的字符串,使用数组将属于的内容设置为引用。

对于等效数组示例,您需要尝试将数组引用设置为新数组:

public static void changeValue(int[] b) {
    b = new int[] { 42, 60 };
}

原始数组不会被更改。

答案 4 :(得分:0)

谢谢大家的答案和更新..

我理解方案1和2之间的区别如下..

在方案1中,传递数组引用。被调用的方法只更新引用指向的元素之一。

在方案2中,引用被传递,但是当被调用的方法将“xyz”赋给引用变量(指针)时,它实际上创建了一个新的String对象,并且它的引用被分配给本地引用变量'a' (指针现在指向一个不同的对象)。

被调用方法中的代码与

一样好
a = new String("xyz");

因此,被调用方法和调用方法中的对象是完全不同且独立的,并且彼此没有关系。

情节1也可能发生同样的情况,如果不是做

b[1] = 9; 

我会用

b = new int[] {8,9,10};

我明白,如果我可能会像下面这样做,可变性基本原理就会起作用。

String a="abc";
a="xyz";

在这种情况下,对象“abc”被“a”指向。当'a'被赋予指向新对象“xyz”的职责时,创建新对象“xyz”,其不替换现有对象“abc”。即“abc”仍然存在但没有参考变量以保持自身可访问。这种非替换属性是由于字符串的不变性。