繁体   English   中英

将对象作为参数传递与将数组作为参数传递有何不同?

[英]How passing an Object as argument differs from passing an Array as argument?

我遇到了两种情况。

一种将数组作为参数传递给方法的方法,如果在调用的方法中对其进行更新,则它也将反映在调用的方法中。

但是在第二种情况下,将字符串对象作为参数传递。 该对象在被调用的方法中更新,但未反映在调用的方法中。

我想了解两者之间的区别,即使在两种情况下,(引用的)值都作为参数传递。 请参阅以下片段。

方案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

如果我在这里套用同样的逻辑,字符串对象值的引用(内存地址)被传递给changeValue,这是由收到a 因此,现在a应该与VALUE所指的是同一存储位置。 因此,当执行a="xyz" ,应将"abc"替换为"xyz"

有人可以指出我的理解错了吗? 提前致谢!!

Java通过值传递其所有参数。 这意味着将创建指向String的指针的副本,然后将其传递给该方法。 然后,该方法使指针指向另一个对象,但是原始指针仍指向同一String。

这不是同一件事:

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

考虑任何对象:

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

一个新的对象被创建,但它不会改变o在调用者。 同样的事情在这里发生。

此处的区别很简单,实际上与字符串的不变性无关,因为其他答案(现在已被编辑或删除)可能最初就暗示了。 在一个版本(带有字符串)中,您已经重新分配了引用,而在另一个版本(带有数组)中,您没有了。

 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分配了一个新对象,变量就不再具有任何共同点。 对于方法内部的参数变量的重新分配也是如此。

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

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

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

原始数组不会更改。

谢谢大家的答复和更新。

我了解方案1和2之间的区别如下。

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

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

调用方法中的代码与

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”仍然存在,但是没有参考变量来保持其自身可访问性。 此不可替换属性是由于String的不可变性。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM