简体   繁体   中英

Java - String immutability and Array mutability

I know that array a and b are pointing to the same place where as Strings s1 , s2 are not. Why?

Code:

    String[] a = {"a","b","c"};
    String[] b = a;
    a[0] = "Z";
    String s1 = "hello";
    String s2 = s1;
    s1 = "world";
    System.out.println(Arrays.toString(a) + " - a"); //a and b are same
    System.out.println(Arrays.toString(b) + " - b");
    System.out.println(s1 + " "+ s2); // s1 and s2 are not same.

Output:

    [Z, b, c] - a
    [Z, b, c] - b
    world hello

At point (2), s1 and s2 are pointing to the same literal in the pool. But when you change s1 , another literal is created and the strings are not pointing to the same place anymore.

String s1 = "hello";
String s2 = s1; (2)
s1 = "world";

You can validate this by printing the result of

s1 == s2

Note that I didn't use equals because I'm interested in comparing references. Now as soon as you assign s1 with a different value, things will look like:

+-------+
| world |  <- s1
+-------+

+-------+
| hello |  <- s2
+-------+

Arrays are objects and thus if you change an array element you change the object which both a and b point to.

Strings are immutable objects so you can only change the reference, what you are doing when calling s1 = "world" .

A little more in-depth explanation:

Strings:

String s1 = "hello"; //creates a new String object with value "hello" and assigns a reference to that object to s1
String s2 = s1;  //s2 now points to the same object as s1
s1 = "world"; //creates a new String object with value "world" and assigns a reference to that object to s1

So in the end s1 will point to a different string object with the value "world".

Arrays:

String[] a = {"a","b","c"}; //creates the array and assigns a reference to it to variable a
String[] b = a; //copies the reference of a to b, so both point to the same object
 a[0] = "Z"; //changes the 1st element in the array, a and b still point to it

Here you never change the actual value of a which is the reference to the array but you rather change the value of the array's 1st element which is itself a reference to the string "Z".

a and b are references to the same Array (there is a single Array object in memory.)

a ---> ["a", "b", "c"] <---- b

You are changing this array value with this line :

a[0] = "Z"

So you know have this in memory :

a ---> ["Z", "b", "c"] <---- b

For the Strings, it's different.

At first, you have two variables pointing the same value :

String s1 = "hello";
String s2 = s1;

You have this in memory :

s1 ---> "hello" <---- s2

But then, you assign s1 to a new value with this code :

s1 = "world";

The variable s2 still points to the string "hello". There are now 2 string objects in memory.

s1 ---> "world" 
s2 ---> "hello"

In Java, Strings are immutable, but arrays are mutable. See also this question .

Note that if you define a class of yours, the behavior will be closer to the Array.

public class Foo() {
  private int _bar = 0;
  public void setBar(int bar) {
    this._bar = bar   
  }
  public void getBar() {
    return this._bar;
  }
}


Foo f1 = new Foo();
Foo f1 = f2;

You have this :

f1 ----> Foo [ _bar = 0 ] <---- f2

You can work on the object :

f1.setBar(1)
f2.setBar(2) // This is the same object

This makes something a bit "like" the array :

f1 ----> Foo [ _bar = 2 ] <---- f2

But if you assign f2 to another value, you get this :

f2 = new Foo();

Which creates a new value in memory, but still keeps the first reference pointing to the first object.

f1 ----> Foo [ _bar = 2 ] 
f2 ----> Foo [ _bar = 0 ]

The key difference is reassignment versus modification.

Reassignment ( x = ... ) makes the variable point to a new object but doesn't change the underlying object, thus any other variables pointing to the original object will not be changed.

Modification ( x.something = ... or x[...] = ... ) only changes the underlying object, thus any other variables pointing to the same object will reflect the changes.

Note that Strings are immutable - they have no methods that modify them and no (non-final) public member variables, so they can't be modified (without reflection).


You can think of people pointing at books being your variables and the books themselves being the underlying objects.

Many people can point at the same book. You can have someone point at a different book without changing the book itself or what anyone else is pointing at. If you write something in a book someone's pointing at everyone pointing to that book will see the changes.

int[] a = {0,1,2,3,4}; // Assign a to, let's say, "Object 1"
int[] b = {5,6,7,8};   // Assign b to, let's say, "Object 2"
int[] c = a;           // Assign c to Object 1
a[0] = 2;              // Change Object 1's 0th element
assert c[0] == 2;      // c points to Object 1, whose 0th element is now 2
a = b;                 // Assign a to Object 2
assert c[0] == 2;      // c still points to Object 1

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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