Home



2017/03 - Passing arguments to methods in Java

Variables are always passed by copy in Java. This is an unchanging rule of the language, but one that can be easily misinterpreted when running code.

Take the following example, which you should place in a package called “misc”:

package misc;

public class ArgumentsAreCopies {

  static int number = 1;

  public static void main(String[] arguments){
    ArgumentsAreCopies copies = new ArgumentsAreCopies();
    System.out.println(“Number before/outside method: ” + number);
    copies.increaseNumber(number);
    System.out.println(“Number after/outside method: ” + number);
  }

  static void increaseNumber(int num){
    num++;
    System.out.println(“Number in method: ” + num);
  }

}

When run, this program should output the following:

Number before/outside method: 1

Number in method: 2

Number after/outside method: 1

This makes sense because, as previously mentioned, arguments are passed as copies. We aren’t changing the original number variable.

However, what happens when we put something that isn’t a primitive type in there, like an object?

Use the following code to create a new class, in the same package:

package misc;
public class TestObject {

  int attributeOne;  int attributeTwo ;
  public void setAttributeOne(int attributeOne) { this.attributeOne = attributeOne; }
  public void setAttributeTwo(int attributeTwo) { this.attributeTwo = attributeTwo; }
  public String toString(){ return “Attribute one: ” + attributeOne + ” Attribute two: ” +       attributeTwo; }

}

For the sake of brevity, this class ignores best practice (getter methods, etc). Change the “ArgumentsAreCopies” class to the following and run it:

package misc;

public class ArgumentsAreCopies {

  static TestObject test = new TestObject();

  public static void main(String[] arguments){

    ArgumentsAreCopies copies = new ArgumentsAreCopies();
    System.out.println(“Test Object outside method: ” + test.toString());
    copies.increaseNumber(test);
    System.out.println(“Test Object outside method: ” + test.toString());

  }

  public void increaseNumber(TestObject test){
    test.setAttributeOne(3);
   System.out.println(“Test Object inside method: ” + test.toString());
  }

}

After running this, you should get the following output:

Test Object outside method: Attribute one: 0 Attribute two: 0

Test Object inside method: Attribute one: 3 Attribute two: 0

Test Object outside method: Attribute one: 3 Attribute two: 0

Looks strange because the field changed this time, right? This isn’t a bug or anything of the sort at all. What’s happening here is that a copy of the TestObject reference is being sent to the method, but  that reference still points to the same object.

We aren’t changing the object (The reference/"pointer" itself) in this case, but instead the fields that both the TestObject reference copy and the original TestObject reference both point towards. They point to the same fields/values from the same object. This is an easy concept to get tripped up on and might not make sense when you first encounter it, but as you continue down the path of Java you will find that the language is very consistent with these kind of “rules”.