String真的不可变吗?

String不变表现形式

 		String str = "ABCabc";
        System.out.println("str="+str);
        str = "123456";
        System.out.println("str="+str);

打印结果

str=ABCabc
str=123456

首先创建一个String对象str,然后让s的值为“ABCabc”, 然后又让s的值为“123456”。 从打印结果可以看出,s的值确实改变了。那么怎么还说String对象是不可变的呢? 其实这里存在一个误区: str只是一个String对象的引用,并不是对象本身。对象在内存中是一块内存区,成员变量越多,这块内存区占的空间越大。引用只是一个4字节的数据,里面存放了它所指向的对象的地址,通过这个地址可以访问对象。 也就是说,str只是一个引用,它指向了一个具体的对象,当str=“123456”; 这句代码执行过之后,又创建了一个新的对象“123456”, 而引用str重新指向了这个新的对象,原来的对象“ABCabc”还在内存中存在,并没有改变。

内存结构:
在这里插入图片描述

String为什么不可变?

查看源码

public final class String
    implements java.io.Serializable, Comparable<String>, CharSequence {
    /** The value is used for character storage. */
    private final char value[];

通过查看源码我们发现String底层的是final修饰的char[]数组。

String真的不可变吗?

我们可以通过反射改变其值:

public static void main(String[] args) throws Exception {

        //创建字符串"Hello World", 并赋给引用s
        String s = "Hello World";

        System.out.println("s = " + s); //Hello World

        //获取String类中的value字段
        Field valueFieldOfString = String.class.getDeclaredField("value");

        //改变value属性的访问权限
        valueFieldOfString.setAccessible(true);

        //获取s对象上的value属性的值
        char[] value = (char[]) valueFieldOfString.get(s);

        //改变value所引用的数组中的第5个字符
        value[5] = '_';

        System.out.println("s = " + s);  //Hello_World
    }

结果

s = Hello World
s = Hello_World
posted @ 2019-10-10 22:53  麦田的老哥  阅读(13)  评论(0)    收藏  举报