Java String 为什么不可变? 真的吗?

简介: Java String 为什么不可变? 真的吗?

众所周知:



Stirng是个不可变的类,因为使用了final来修饰(真的只是这个一个final的功劳吗? ),如:


image.png


又有一个众所周知:



就是 String的本质是一个char[] 数组


所以为了确保String真的不可变,那么本质肯定不能变,于是乎这个char[]数组,如:


image.png


而且这个成员变量是没有提供set和get方法。


看到这里,其实可以知道的就是,如果这个value数组的元素被改变了,那么String就是被改变了。


所以在String的源码里,诸多方法里面都没有涉及到直接去修改value[]的元素。

 

再度聚焦:image.png


这个构造函数,一眼能看明白意思,就是通过传递一个char 数组,进行构造出一个新的String。


但是又细眼一看?


 image.png


这里使用到了Arrays的copyOf方法去实现深拷贝:


image.png


这样做的原因大家都知道,就是重新开辟一波新的空间,这样防止 在后续修改传入的char value[] 里的元素,导致String也跟着被修改(如果写成 this.value=value)


霸王硬上弓:



那么咱们就是要修改String,怎么办?


那肯定就是修改它的本质 char[] value的元素了。


咱们通过反射去修改String的成员变量,也就是这个本质 char数组,一起来看看:


    public static void main(String[] args) throws NoSuchFieldException, IllegalAccessException {
        String testStr = "JCccc";
        System.out.println("一开始的testStr值为 : " +testStr);
        System.out.println(testStr.hashCode());
        //反射机制,获取获取String里面的的value字段
        Field valueFieldOfString = String.class.getDeclaredField("value");
        //设置value属性的访问权限为true
        valueFieldOfString.setAccessible(true);
        //获取s对象上的value属性的值
        char[] value = (char[]) valueFieldOfString.get(testStr);
        //改变value数组中的元素
        value[1] = 'A';
        value[2] = 'a';
        System.out.println("被操作之后的testStr为 : " +testStr);
        System.out.println(testStr.hashCode());
    }


看一下效果:


image.png


好了,该篇就到此。

相关文章
|
2月前
|
Java UED
Java中String强转int:一种常见的错误和解决方法
在Java中将非数字字符串转换为整数会导致`NumberFormatException`。要解决这个问题,可以使用`try-catch`捕获异常,正则表达式验证数字格式,或利用异常信息提供错误提示。例如,`Integer.parseInt()`会因遇到非数字字符如`"123abc"`而抛出异常,但通过异常处理或正则`\\d+`可确保安全转换。记得在编程时避免直接强转,以防止程序异常中断。
|
4天前
|
前端开发 Java
成功解决:java.lang.String cannot be cast to java.lang.Integer
这篇文章记录了作者在使用Axios二次封装时遇到的一个Java类型转换问题,即前端传递的字符串参数不能直接转换为Integer类型,文章提供了正确的转换方法来解决这个问题。
成功解决:java.lang.String cannot be cast to java.lang.Integer
|
7天前
|
Java Android开发
解决Android编译报错:Unable to make field private final java.lang.String java.io.File.path accessible
解决Android编译报错:Unable to make field private final java.lang.String java.io.File.path accessible
25 1
|
11天前
|
XML Java 数据库连接
Mybatis java.lang.NumberFormatException: For input string: "1,2" 问题处理
【8月更文挑战第9天】Mybatis java.lang.NumberFormatException: For input string: "1,2" 问题处理
|
11天前
|
安全 Java
12 Java常用类(二)(String类+时间类+BigDecimal类等等)
12 Java常用类(二)(String类+时间类+BigDecimal类等等)
23 2
|
21天前
|
Java
Java中将保留四位小数的Double转换为String的方法详解
选择合适的方法,可以使代码更加简洁、高效,同时也能满足不同场景下的需求。
22 5
|
1月前
|
安全 Java
Java基础之StringBuffer
【7月更文挑战第1天】 Java中的`StringBuffer`是线程安全的字符串操作类,适合多线程环境,而`StringBuilder`非线程安全,速度更快,适用于单线程。两者提供`append()`、`insert()`、`delete()`等方法修改字符串,避免了频繁创建新对象的性能问题。在不需要线程安全时,推荐使用`StringBuilder`以提高效率。
19 1
|
1月前
|
安全 Java 索引
带你快速掌握Java中的String类和StringBuffer类(详解常用方法 | 区别 )
带你快速掌握Java中的String类和StringBuffer类(详解常用方法 | 区别 )
|
2月前
|
Java 数据处理 Apache
探讨Java中判断String类型为空和null的方法
探讨Java中判断String类型为空和null的方法
24 1
|
2月前
|
存储 SQL 关系型数据库
【BUG记录】Cause: java.sql.SQLException: Incorrect string value: '\xF0\x9F\x90\xA6' for column 'name' at row 1
在MySQL中遇到`Incorrect string value`错误通常是因为尝试插入的字符串包含不被数据库字符集支持的字符,如表情符号。错误根源是MySQL默认的utf8不支持4字节的UTF-8字符(如Emoji)。
39 1