简体   繁体   English

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

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

I have come across two scenarios. 我遇到了两种情况。

One in which an array is passed as argument to a method and if it is updated in the called method, it is reflecting in the calling method as well. 一种将数组作为参数传递给方法的方法,如果在调用的方法中对其进行更新,则它也将反映在调用的方法中。

But in the second scenario, a String Object is passed as argument. 但是在第二种情况下,将字符串对象作为参数传递。 The object is updated in the called method, but it doesn't reflect in the calling method. 该对象在被调用的方法中更新,但未反映在调用的方法中。

I want to understand what is the difference between two, even though in both cases, value (of reference) is passed as argument. 我想了解两者之间的区别,即使在两种情况下,(引用的)值都作为参数传递。 Please see below snippets. 请参阅以下片段。

Scenario 1: 方案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;
}
}

Output: 输出:

Value at Index 1 is 9

Here, reference (Memory Address) related to array a is passed to changeValue . 这里,与数组a相关的引用(内存地址)传递给changeValue Hence, b is just pointing to same address as a does. 因此, b只是指向同一地址作为a做。 Hence, whether I say b[1] or a[1] , it is referring to same memory address. 因此,无论我说b[1]还是a[1] ,它都是指相同的内存地址。

Scenario 2: 方案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";
}
}

Output: 输出:

abc

If I apply the same logic here, String Object VALUE's reference (Memory Address) is being passed to changeValue, which is recieved by a . 如果我在这里套用同样的逻辑,字符串对象值的引用(内存地址)被传递给changeValue,这是由收到a Hence, now a should be referring to the same memory location as VALUE does. 因此,现在a应该与VALUE所指的是同一存储位置。 Therefore, when a="xyz" is executed, it should replace "abc" with "xyz" . 因此,当执行a="xyz" ,应将"abc"替换为"xyz"

Can someone please point out where my understanding goes wrong? 有人可以指出我的理解错了吗? Thanks in advance!! 提前致谢!!

Java passes all its arguments by value. Java通过值传递其所有参数。 This means that a copy of the pointer to the String is made, and then passed to the method. 这意味着将创建指向String的指针的副本,然后将其传递给该方法。 The method then makes the pointer point at another object, but the original pointer still points to the same String. 然后,该方法使指针指向另一个对象,但是原始指针仍指向同一String。

This is not the same thing: 这不是同一件事:

  • in the first example, you pass an array reference as an argument, therefore you correctly expect it to be changed by manipulating the reference directly; 在第一个示例中,您将数组引用作为参数传递,因此您可以正确地期望直接操作该引用来更改它;
  • in the second example however, you pass an object reference, sure -- but you change the reference itself in the method. 但是,在第二个示例中,您肯定传递了对象引用-但是您在方法中更改了引用本身。 Changes to a are not reflected when the method returns. 方法返回时,不会反映对a更改。

Consider any object: 考虑任何对象:

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

a new object is created, but it won't change o in the caller. 一个新的对象被创建,但它不会改变o在调用者。 The same happens here. 同样的事情在这里发生。

The difference here is simple, and it is not actually about immutability of strings, as some other answers (now edited or deleted) might have originally implied. 此处的区别很简单,实际上与字符串的不变性无关,因为其他答案(现在已被编辑或删除)可能最初就暗示了。 In one version (with the string), you have reassigned the reference, and in other version (with the array), you haven't. 在一个版本(带有字符串)中,您已经重新分配了引用,而在另一个版本(带有数组)中,您没有了。

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

When you reassign the variable , you are not going to observe that change outside of the method. 当您重新分配变量时 ,您将不会在方法之外观察到该更改。 When you change elements of an array without reassigning the array variable, you will observe those changes. 当您在不重新分配数组变量的情况下更改数组元素时,将观察到这些更改。 When you call a setter on an object without reassigning the actual variable of the object, you will observe those changes. 当您在不重新分配对象实际变量的情况下调用对象的setter时,将观察到这些更改。 When you overwrite the variable (new array, assigning new value, creating new object, etc.) those changes will go unobserved. 当您覆盖变量(新数组,分配新值,创建新对象等)时,这些更改将不可观察。

Arguments are passed (or copied) by value. 参数通过值传递(或复制)。 The variable inside the method has the same value as the variable on the outside at the beginning. 方法内部的变量开头与外部的变量具有相同的值。 The variables are not linked, and they are not aliases for one another. 这些变量没有链接,也不是彼此的别名。 They just happen to contain the same value. 它们恰好包含相同的值。 Once you reassign the value to one of them, that is no longer true! 一旦将值重新分配给其中之一,那就不再是事实! The variable on the outside is not affected by the variable on the inside, or even another local variable. 外部变量不受内部变量甚至其他局部变量的影响。 Consider 考虑

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

foo and other only referenced the same object for a time. fooother只引用同一对象。 Once foo was assigned a new object, the variables no longer had anything in common. 一旦为foo分配了一个新对象,变量就不再具有任何共同点。 The same is true for your reassignments to the parameter variable inside your method. 对于方法内部的参数变量的重新分配也是如此。

You're doing different things; 您正在做不同的事情; with the string you set the parameter value, with the array you set something belonging to the reference. 使用设置参数值的字符串,使用数组设置属于引用的内容。

For an equivalent array example you'd need to try setting the array reference to a new array: 对于等效的数组示例,您需要尝试将数组引用设置为新数组:

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

The original array won't be changed. 原始数组不会更改。

Thank you all for answers and updates.. 谢谢大家的答复和更新。

I understood the difference between scenario 1 and 2 as below.. 我了解方案1和2之间的区别如下。

In scenario 1, the array reference is passed. 在方案1中,将传递数组引用。 The called method just updates one of the elements pointed by the reference. 被调用的方法只是更新引用指向的元素之一。

While in scenario 2, the reference is passed, but when the called method assigns "xyz" to the reference variable (pointer), it actually creates a new String Object and its reference is assgined to a local reference variable 'a' (Pointer now points a different objct). 在方案2中,虽然传递了引用,但是当被调用的方法将“ xyz”分配给引用变量(指针)时,它实际上创建了一个新的String对象,并且其引用被关联到本地引用变量“ a”(现在为Pointer指向不同的对象)。

The code in called method is as good as 调用方法中的代码与

a = new String("xyz");

Hence, the object in called method and calling method are absolutely different and indepenedent and have no relation with each other. 因此,被调用方法和调用方法中的对象是绝对不同且独立的,彼此之间没有关系。

The same could have happened with scenario 1, if instead of doing 如果不这样做,情况1也可能发生相同的情况

b[1] = 9; 

I would have used 我本来会用

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

I understood, Mutability fundamentals would have come in action, if I might have done like below.. 我了解,如果我可以像下面那样做,则可变性基本原理将付诸实践。

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

In this case, object "abc" was being pointed by 'a'. 在这种情况下,对象“ abc”由“ a”指向。 When 'a' is assigned the duty to point to a new object "xyz", a new object "xyz" is created, which is not replacing the existing object "abc". 当为“ a”分配了指向新对象“ xyz”的职责时,将创建一个新对象“ xyz”,而不替换现有对象“ abc”。 ie "abc" is still existing but has no reference variable to keep itself accessible anymore. 也就是说,“ abc”仍然存在,但是没有参考变量来保持其自身可访问性。 This non-replacement property is because of Immutability of String. 此不可替换属性是由于String的不可变性。

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

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