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. Vue -- 项目报错整理(1):RangeError: Maximum call stack size exceeded

    这几天项目运行报了个错: Uncaught RangeError: Maximum call stack size exceeded,刚开始看到 "returnNodeParameter&q ...

  2. Python Django框架笔记(二):创建应用和django 管理

    #前提是已经创建项目 (一)      创建应用 使用命令,在项目中创建一个应用(blog自定义) python manage.py startapp blog 创建完成后,可以看到下面几个文件 文件 ...

  3. continue break exit用法说明

    1,continue用法 2,break用法 3,sys.exit用法 1,continue用法(跳出本次循环,继续下次循环) for i in xrange(10): if i == 8: cont ...

  4. sql 经典面试题及答案(选课表)

    SQL数据库面试题以及答案 Student(Sno,Sname,Sage,Ssex) 学生表       Sno:学号:Sname:学生姓名:Sage:学生年龄:Ssex:学生性别Course(Cno ...

  5. 红帽7中firewall常用指令

    1.端口管理 (1)列出DMZ区域开放的端口 ~]#firewall-cmd --zone=dmz --list-ports (2)8080端口加入dmz区 ~]#firewall-cmd --zon ...

  6. MySQL分析函数实现

    | MySQL分析函数实现还好MySQL8.0已经实现了与Oracle相同的分析函数. 1. 实现rownumSET @rn:=0;SELECT @rn:=@rn+1 AS rownum ,e.* F ...

  7. MySQL复制 slave_exec_mode 参数IDEMPOTENT 说明

      背景: 今天无意当中看到参数slave_exec_mode,从手册里的说明看出该参数和MySQL复制相关,是可以动态修改的变量,默认是STRICT模式(严格模式),可选值有IDEMPOTENT模式 ...

  8. 【Alpha 冲刺】 1/12

    1. 任务明细及任务量 Alpha版本任务安排(非固化版本,视情况调整,若有遗漏,及时补充) 职务 姓名 预期负责的模块页面 模块页面/任务明细 难度系数(0~1)(根据UI/功能实现难度划分) 预计 ...

  9. Python接口自动化--post提交的四种数据类型 4

    常见的post请求提交的数据类型有四种: 1.第一种:application/json:这是最常见的json格式,如下 {"input1":"XXX",&quo ...

  10. Linux基础第一课——基础知识了解

    前言 发展历史 linus 林纳斯 赫尔辛基大学 在自己的笔记本上安上自己写的操作系统 基于Linux内核 Linux内核 也是基于unix内核开发出来 unix 不开源 只能军方和大学使用 Linu ...