Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Setting equal in Java: by value or reference?

I did two tests, the first starting with Strings

    String str1 = "old";
    String str2 = str1;
    str1 = "new";

    System.out.println(str1); //new
    System.out.println(str2); //old

The above example indicates that str2 = str1, by value

Now I do the similar operations, but this time with Lists

    List<Integer> list1 = new ArrayList<Integer>();
    List<Integer> list2 = list1;
    list1.add(1);

    System.out.println(list1.size()); //1
    System.out.println(list2.size()); //1

This example indicates that list2 = list1, by reference

I am confused, which Java variables/objects are passed by value and which are passed by reference?

like image 939
onepiece Avatar asked Mar 05 '14 04:03

onepiece


People also ask

Does Java assign by reference or value?

Java is always Pass by Value and not pass by reference, we can prove it with a simple example. Let's say we have a class Balloon like below. And we have a simple program with a generic method to swap two objects, the class looks like below.

Are Java parameters passed by reference?

Java always passes arguments by value, NOT by reference.

Does Java support call by reference?

Java does not support call by reference because in call by reference we need to pass the address and address are stored in pointers n java does not support pointers and it is because pointers breaks the security. Java is always pass-by-value.

Why Java is strictly pass by value?

Object references are passed by value The reason is that Java object variables are simply references that point to real objects in the memory heap. Therefore, even though Java passes parameters to methods by value, if the variable points to an object reference, the real object will also be changed.


2 Answers

In your first code, yes, this line

String str2 = str1;

Assigns str2 to the same String referred by str1, that is, "old". At this point, they are the same object. However, the next line

str1 = "new";

create a new instance of String, and changes the reference of str1 to this new String. As we are changing the reference of str1, the content of str2 are not changed.

Pay attention that Java, Strings are immutable i.e. cannot change state once initialized. Thinking this way, content of "old" may never change. So when you assign "new" to str1, you don't change the value of "old", you create a new String instead.

In other words, this line, in here, is the same as

str1 = new String("new");

http://i.minus.com/jboQoqCxApSELU.png

However, in the second code,

List<Integer> list2 = list1;

make list2 refer to the same list as list1. As a result, list1 and list2 refer to the same list. Then

list1.add(1); 

adds an element to the list referred by list1. However, as I have said, list1 and list2 refer to same list, both list1 and list2 now have the element 1. There is no new instance created in the method call.

http://i.minus.com/jxDLyBqcUzgHZ.png

In fact, if you were to do

List<Integer> list1 = new ArrayList<Integer>();
List<Integer> list2 = list1;
list1 = new ArrayList<Integer>();
list1.add(1);

System.out.println(list1.size()); //1
System.out.println(list2.size()); //0

because list1 = new ArrayList<Integer>(); reassigns list1 to a new list, that no longer refer to the object referred by list2.


After all the assignment operator (i.e. obj1 = obj2) always copy the references, which two references will still refer to the same object instance after the assignment. This is for both String, List, or any other classes (But not primitive types).

However, str1 = "new" will, in most cases, create a new instance of String and then assign the reference to the new String to str1 - this is a special case in the Java lanaguage. This don't apply to any other kind of objects. This is different to any other method call like list1.add(1).

like image 121
luiges90 Avatar answered Oct 26 '22 17:10

luiges90


Your difference is here

str1 = "new";

vs

list1.add(1);

In the String example, you are changing references. Changing the reference of str1 does not affect any other variables.

In the List example, you are invoking a method, which dereferences the reference and accesses the object. Any variables referencing that same object will see that change.

Here it is

List<Integer> list1 = new ArrayList<Integer>(); // 1
List<Integer> list2 = list1; // 2 
list1.add(1); // 3

looks like this

   1:  list1 ===> object1234
   2:  list1 ===> object1234 <=== list2
   3:  list1 ===> object1234 (internal modification) <=== list2
like image 33
Sotirios Delimanolis Avatar answered Oct 26 '22 16:10

Sotirios Delimanolis