Question

I have a question regarding the concept of Java using pass-by-value. I do a lot of programming in C but I am very inexperienced with Java so I have been writing some code to learn a bit more about it. I have read many stack-overflow questions regarding whether there is ever any pass-by-reference, the answer seems to be that Java always uses pass-by-value (with the slight deviation being it passes references to objects by value).

With this in mind I’ve managed to properly confuse myself, I don’t understand how the following example can be an instance of pass-by-value. I would appreciate an explanation as to the internal Java workings that I don’t understand.

I have the following code:

byte[] myByteArray = {23, 45, 67};
myHashMap.put(myKey, new TestClass(100, myByteArray, myOtherByteArray));
Arrays.fill(myByteArray, (byte)0);

Where myHashMap is a ConcurrentHashMap and TestClass is defined:

public class TestClass
{
  public final int number;
  public final byte[] byte1;
  public final byte[] byte2;

  public TestClass(int a, byte[] b, byte[] c)
  {
    number = a;
    byte1 = b;
    byte2 = c;
  }
}

When I use the debugger to step through the code I can see that the byte1 variable stored in TestClass (And subsequently in the ConcurrentHashMap) is altered by the Arrays.fill call, my question is ... why?

When instantiating a new TestClass am I not passing myByteArray by value?

Was it helpful?

Solution

All objects are used by passing a reference which is itself passed by value unless cloned using a copy constructor or Cloneable's clone() in which case the value of a reference to a new object is passed. Arrays are objects as well, and as thus are referents in this way. If one is modified, all other references held to it will reflect these changes.

OTHER TIPS

Java is pass by value.

Always.

The only tricky part is passing arguments to methods, which is described in this stack overflow question.

(copy of important answer below)


Java is always pass-by-value. The difficult thing can be to understand that Java passes objects as references and those references are passed by value.

It goes like this:

public void foo(Dog d) {
  d.getName().equals("Max"); // true
  d = new Dog("Fifi");
  d.getName().equals("Fifi"); // true
}

Dog aDog = new Dog("Max");
foo(aDog);
aDog.getName().equals("Max"); // true In this example aDog.getName() will still return "Max". d is not overwritten in the function as the object reference is passed by value.

Likewise:

public void foo(Dog d) {
  d.getName().equals("Max"); // true
  d.setName("Fifi");
}


Dog aDog = new Dog("Max");
foo(aDog);
aDog.getName().equals("Fifi"); // true

Your confusion is because the premise of your question is flawed -- "arrays" cannot be passed. Arrays are objects, and objects are not values in Java. The only types in Java are primitive types and reference types (note: no "object types"), so the only values in Java are primitives and references.

When I use the debugger to step through the code I can see that the byte1 variable stored in TestClass (And subsequently in the ConcurrentHashMap) is altered by the Arrays.fill call, my question is ... why?

Your byte1 variable has not been altered. byte1 has a reference type; i.e. it is a reference. Its value is a memory address. This value remains the same.

The array object that is pointed to by byte1 has had its contents changed.

When instantiating a new TestClass am I not passing myByteArray by value?

Yes, you are.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top