Is String a Value Type or a Reference Type

It has always been remembered that except for the eight basic types (byte, short, char, int, long, float, double, boolean), other types of JAVA language are all reference types. However, today someone told me that String is a value type, which was confused. Back to Baidu, some people said that String is a value type, others said that String is a reference type. Everyone has their own opinion.

Well, it's better to ask for yourself than to practice to get the truth.

First, state the conclusion: String in Java is an authentic reference type, but under certain conditions, String shows certain value characteristics. Paste the code and start:

public class MainActivity extends Activity {
 
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
 
        Toast.makeText(this, "test1() = " + test1(), Toast.LENGTH_LONG).show();
        Toast.makeText(this, "test2() = " + test2(), Toast.LENGTH_LONG).show();
        Toast.makeText(this, "test3() = " + test3(), Toast.LENGTH_LONG).show();
    }
 
 
    private boolean test1() {
        String a = "123";
        String b = "123";
        return a == b;
    }
 
    private boolean test2() {
        String a = new String("123");
        String b = new String("123");
        return a == b;
    }
 
    private boolean test3() {
        String a = "123";
        doTest3(a);
        return TextUtils.equals("123", a);
    }
 
    private void doTest3(String str) {
        str = str + "123";
    }
}

Start with test1:

test1() returns true, which looks a bit like a value type. However, everything can be explained:

First analyze:

String a = "123";

and

String a = new String("123");

The difference is:

  • The String object of the former is allocated in the heap, but the pointer to the String object is saved in the constant pool, while a is a String pointer. The content of the pointer is the same as the pointer corresponding to "123" in the constant. Specifically, the execution is as follows:

    • First, find a pointer to "123" in the constant pool
    • If the "123" pointer cannot be found in the constant pool, allocate "123" memory space in the heap, save the address in the constant pool, and assign the address to the String pointer a
    • If a pointer to "123" is found in the constant pool, the entity "123" already exists in the heap. Because a constant represents an immutable object, it is not necessary to create a new instance and assign the pointer contents in the constant pool directly to the String pointer a.
  • While the latter actually involves two String entities,'123'has one entity in the heap and a pointer to'123' in the constant pool, new String() creates a new String entity in the heap, deeply copies the contents of'123', returns the address of the new String entity, and assigns it to pointer a

      So,`test1`Medium, a and b Both pointers point to a constant.`123`"Entities whose values are equal, so`a==b`by`true`. 
    
      and`test2`Medium, a and b Both pointers point to their respective`String`Entity, although two`String`Entities are deeply copied from the constant.`123`",So the content is the same, but because it's not the same`String`Entities, so memory addresses are different,`a==b`by`false`. 
    
      When it comes to this, by the way, explain one C#and Java Differences:`C#`For all`String`Objects are constants, so the content is deterministic`String`An entity has only one instance on the heap. So if`test2`Function to C#Language implementation, there will only be one instance,`a==b`by`true`,That's why`C#`String`, although a reference type, can use the `==` operator to determine why two strings are equal.
    
      Come on`test3`
    
      At first glance,`string`Types are passed as references and seem to be`doTest3`The function changes, so`TextUtils.equal("123","123123")`Should be`false`Yes, but the actual test results are:`test3()`Return value is`true`. 
    
      Here, let me analyze the reason by debugging:
    
  • First, create a, a entity address of "830042018440"

Next, into the doTest3 function, str's entity address is also "830042018440", when there are two pointers in memory, a and str, both pointing to the same String entity

  • Then we find that the str pointer points to a new entity "123123" with the address "830042152712", but this does not affect the a pointer, which still points to the previous entity "123"
  • Finally, the function returns that the a pointer actually points to "123", so TextUtils.equal("123","123") returns true

Summary:

I think the previous explanation is clear. String types are really reference types, although in some cases they look like value types.

In addition, I believe some careful friends have discovered that the implementation of String is actually char[] plus variable count (offset and hash code are ignored first). It is true that String can be attributed to char[], since char[] is a reference type, how can String be a value type?

Tags: C#

Posted on Wed, 08 Sep 2021 14:04:08 -0400 by Schism