简体   繁体   English

反直觉对象参数行为

[英]Counter Intuitive Object Parameter Behaviour

I am well aware that Java passes parameters by value, and how that since objects are kept in varaibles as references it is possible to change object values when those values are mutable. 我很清楚Java通过值传递参数,并且由于对象是作为变量保存在变量中作为引用的,因此当值可变时可以更改对象值。 What I also understand is that class String contains objects that are immutable. 我还了解的是,String类包含不可变的对象。 So, to test my understand I decided to write a bit of code that would pass an object to a method as a parameter, change both its string and int variables, and then print it. 因此,为了测试我的理解,我决定编写一些代码,该代码将对象作为参数传递给方法,同时更改其字符串和int变量,然后进行打印。 I expected that, since the parameter is merely a copy, these changes would not affect the variable passed in. Does passing in an object as a parameter not copy the entire object into a new variable an simply passes that objects reference? 我期望,由于参数只是一个副本,因此这些更改不会影响传入的变量。将对象作为参数传入不会将整个对象复制到新变量中吗? This is counter to what I have been told by several sources. 这与几个消息来源告诉我的情况相反。 Here is the code in question: 这是有问题的代码:

public class Test {


    public int testVar = 20;
    public String testString = "Hello";

    public static void testCheck(Test test){
        test.testString = new String("GoodBye");
        test.testVar = 10;
    }

    public void printTest(){
        System.out.println("testVar: " + testVar + " testString: " + testString);
    }

    public static void main(String[] args) {
        Test test1 = new Test();
        test1.printTest();
        testCheck(test1);
        test1.printTest();

    }

}

Output: 输出:

testVar: 20 testString: Hello 

testVar: 10 testString: GoodBye 

Expected: 预期:

testVar: 20 testString: Hello

testVar: 20 testString: Hello

Thanks in advance. 提前致谢。

A few concepts: 一些概念:

  • An object is aa construct which has data and behavior. 对象是具有数据和行为的构造。
  • An variable is a construct that stores a value. 变量是存储值的构造。
  • An object reference is a value which references an object. 对象引用是引用对象的值。
  • Variables of reference types (all types that aren't primitive types) store object references as their value. 引用类型的变量(不是原始类型的所有类型)将对象引用存储为其值。
  • When you access a field or invoke a method from a variable, the JVM dereferences the value of the object reference, gets the object, and does the access or invocation for you. 当您访问字段或从变量调用方法时,JVM取消引用对象引用的值,获取对象,并为您执行访问或调用。

This last point is what you are doing in your testCheck method. 最后一点是您在testCheck方法中正在做的事情。 Also, 也,

  • A method parameter is aa variable declared in a method definition. 方法参数是在方法定义中声明的变量。
  • A method argument is a value which you'd like bound to a method parameter when invoking a method. 方法参数是调用方法时要绑定到方法参数的值。
  • Java passes (by-value) and binds the value of the object reference to the method parameter. Java传递(按值)并将对象引用的值绑定到method参数。

Does passing in an object as a parameter not copy the entire object into a new variable an simply passes that objects reference? 将对象作为参数传递不会将整个对象复制到新变量中,而只是传递该对象引用吗?

That sentence doesn't make much sense. 那句话没有多大意义。 What you're passing as an argument is a value. 您作为参数传递的是一个值。 That value is an object reference, not an object. 该值是对象引用,而不是对象。 In your method, you dereference that object reference to access fields and invoke methods of the referenced object. 在您的方法中,可以取消引用该对象引用以访问字段并调用所引用对象的方法。

In Java, parameters are always passed by value, so test is actually a copy of test1 . 在Java中,参数始终按值传递,因此test实际上是test1的副本。 The mistake you're making is that copying an object variable does not copy the object ; 您犯的错误是,复制对象变量不会复制对象 it copies the reference to the same object. 它将引用复制到同一对象。 Since you're mutating the fields on the same object instance, both references are seeing the new state. 由于您要对同一对象实例上的字段进行突变,因此两个引用都将看到新状态。 By contrast, when you "update" an immutable object variable, like a String , you're just referencing a new object instance. 相反,当您“更新”一个不可变的对象变量(如String ,您只是在引用一个新的对象实例。

By the way, there's rarely a good reason to create a new String instead of just assigning a string literal. 顺便说一句,很少有理由创建new String而不是仅仅分配字符串文字。 Definitely none in this case. 在这种情况下绝对没有。

You are passing a copy of the reference to the original object. 您正在将引用的副本传递给原始对象。 In effect, you are passing the original object's reference, and so in: 实际上,您正在传递原始对象的引用,依此类推:

testCheck(test1);

you are modifying the test1 object's properties/variables. 您正在修改test1对象的属性/变量。

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

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