0. 前言  

如果一个对象,在它创建完成之后不能再改变它的状态,包括对象内的成员变量、基本数据类型的值等等。那么这个对象就是不可变的。众所周知String类就是不可变的。转载请注明出处为SEU_Calvin的博客

1. String类为什么是不可变的 

首先看一下String类的源码中:

//JDK1.6
public final class String
implements java.io.Serializable, Comparable<String>, CharSequence
{
/**用于存储字符的数组 */
private final char value[];
/** 表示String在这个value数组中的起始位置 */
private final int offset;
/** 字符个数*/
private final int count;
/** 哈希值 */
private int hash; // Default to 0
//...
} //JDK1.7
public final class String
implements java.io.Serializable, Comparable<String>, CharSequence {
/**用于存储字符的数组 */
private final char value[];
/** 哈希值 */
private int hash; // Default to 0
//....
}

从源码中可以看出,无论是JDK6还是7,虽然内部成员有所改变,但是String类终究是对字符数组的封装。而且value也只是一个引用,它指向一个真正的数组对象。源码中并没有提供value的set方法,因此String类一旦初始化,外部便无法修改,同时value被修饰为 private final,在String类内部也无法改变。所以String对象是不可变的。

我们常用的字符串方法比如substring、replace、replaceAll、toLowerCase等方法,给人的感觉好像是可以改变String内的值,但是这些方法的内部其实在完成逻辑后创建了一个新的String对象并返回。以replace为例,以下是一个简单的例子证明这一点。

String s = "DF2lian";
s = s.replace('F', 'A');
System.out.println("s = " + s); //输出DA2lian String s = "DF2lian";
s.replace('F', 'A');
System.out.println("s = " + s); //输出DF2lian

2. String类真的不可变吗 

从上文可知String的成员变量value是private final修饰的,初始化后不可再改变并且不能再指向其他数组对象。但是value本身是一个引用变量,而不是真正的对象。那么我们就可以通过反射得到String对象中的value属性,进而改变value引用的数组的结构。下面是实例代码:

String s = "DF2lian";
//获取String类中的value字段
Field valueFieldOfString = String.class.getDeclaredField("value");
//改变value属性的访问权限
valueFieldOfString.setAccessible(true);
//获取s对象上的value属性的值
char[] value = (char[]) valueFieldOfString.get(s);
//改变value所引用的数组中某个字符
value[1] = 'R';
System.out.println("s = " + s); //输出DR2lian

Java技术——String类为什么是不可变的的更多相关文章

  1. Java的string类为什么是不可变的

    最流行的Java面试题之一就是:什么是不可变对象(immutable object),不可变对象有什么好处,在什么情况下应该用,或者更具体一些,Java的String类为什么要设成immutable类 ...

  2. java中String类为什么不可变?

    在面试中经常遇到这样的问题:1.什么是不可变对象.不可变对象有什么好处.在什么情景下使用它,或者更具体一点,java的String类为什么要设置成不可变类型? 1.不可变对象,顾名思义就是创建后的对象 ...

  3. 深入分析Java的String类的方法与特点

    字符串是任何编程语言都必须支持的变量类型,有些编程语言是直接提供了原生的变量类型,有些编程语言则使用语法特性以 SDK 的形式提供支持.在Java编程平台中,对字符串的支持使用了后者的形式,就是通过在 ...

  4. java里String类为何被设计为final

    前些天面试遇到一个非常难的关于String的问题,"String为何被设计为不可变的"?类似的问题也有"String为何被设计为final?"个人认为还是前面一 ...

  5. 在java中String类为什么要设计成final?

    大神链接:在java中String类为什么要设计成final? - 程序员 - 知乎 我进行了重新排版,并且更换了其中的一个例子,让我们更好理解. String很多实用的特性,比如说“不可变性”,是工 ...

  6. Java之String类

    String类概述 java.lang.String 类代表字符串.Java程序中所有的字符串文字(例如 "abc" )都可以被看作是实现此类的实例.其实就是说:程序当中所有的双引 ...

  7. Java中String类为什么被设计为final?

    Java中String类为什么被设计为final   首先,String是引用类型,也就是每个字符串都是一个String实例.通过源码可以看到String底层维护了一个byte数组:private f ...

  8. 『Java』String类使用方法

    Java中的字符串 java.lang.String类表示字符串类,Java程序中所有字符串文字都可以看作实现该类的实例. 特点: 字符串不可变:字符串的值在创建后不能在发生改变 public cla ...

  9. Java中String类的方法及说明

    String : 字符串类型 一.      String sc_sub = new String(c,3,2);    //      String sb_copy = new String(sb) ...

随机推荐

  1. ConstraintLayout (约束布局)属性详情

    本文部分内容来自于网络,点击浏览原文 app:layout_constraintLeft_toLeftOf //Constrains the left side of a child to the l ...

  2. 【Python】keras神经网络识别mnist

    上次用Matlab写过一个识别Mnist的神经网络,地址在:https://www.cnblogs.com/tiandsp/p/9042908.html 这次又用Keras做了一个差不多的,毕竟,现在 ...

  3. LeetCoder题解之Find All Anagrams in a String

    1.题目描述 2.题目分析 直接使用 哈希表记录子串的信息,然后对比两个哈希表信息即可 3.代码 vector<int> findAnagrams(string s, string p) ...

  4. Microsoft SQL 关系数据库的使用指南

    Microsoft SQL 关系数据库的使用指南 https://docs.microsoft.com/zh-cn/sql/relational-databases/database-features

  5. IE中操作粘贴板复制和粘贴

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  6. sysbench使用

      1 部署 1.1 官方主页 https://github.com/Percona-Lab/sysbench-tpcc https://github.com/akopytov/sysbench 1. ...

  7. ajax status 错误

    status **:未被始化 status **:请求收到,继续处理 status **:操作成功收到,分析.接受 status **:完成此请求必须进一步处理 status **:请求包含一个错误语 ...

  8. unbuntu 安装python包提示E: Unable to locate package python-timeout

    今天本想着在unbuntu环境下安装python的一个包,安装了几次都提示 E: Unable to locate package python-timeout 查阅了一些信息才知道,原来是一些软件源 ...

  9. java调用Linux执行Python爬虫,并将数据存储到elasticsearch--(环境脚本搭建)

    java调用Linux执行Python爬虫,并将数据存储到elasticsearch中 一.以下博客代码使用的开发工具及环境如下: 1.idea: 2.jdk:1.8 3.elasticsearch: ...

  10. 代理工具--mitmproxy

    #代理工具 mitmproxy 指令:mitmproxy -b ip -p port(代理ip设置为:ip,端口设置为:port) 拦截request: 输入字母“i”(代表Intercept fil ...