WindTorn
WindTorn

Reputation: 3

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. What I also understand is that class String contains objects that are immutable. 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. 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.

Upvotes: 0

Views: 77

Answers (3)

shmosel
shmosel

Reputation: 50716

In Java, parameters are always passed by value, so test is actually a copy of 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.

By the way, there's rarely a good reason to create a new String instead of just assigning a string literal. Definitely none in this case.

Upvotes: 1

Sotirios Delimanolis
Sotirios Delimanolis

Reputation: 279960

A few concepts:

  • An object is a a 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.

This last point is what you are doing in your testCheck method. Also,

  • A method parameter is a a 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.

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.

Upvotes: 1

Martin Dinov
Martin Dinov

Reputation: 8825

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.

Upvotes: 0

Related Questions