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. OkHttp实现文件上传进度

    文件上传就一个没刻度的进度条在那里转怎么行,本篇带你实现上传进度,为你的进度条添加刻度吧,啥都不说了,重点重写RequestBody,看代码 import com.squareup.okhttp.*; ...

  2. JSTL核心标签库——<c:set>标签、<c:out>标签

    <c:set>标签 index.jsp <%@ page import="java.util.Map" %> <%@ page import=&quo ...

  3. SQLSERVER中的LOB页面简单研究

    SQLSERVER中的LOB页面简单研究 这篇文章和我另一篇文章是相辅相成的,在看<SQLSERVER2012 列存储索引的简单研究和测试>这篇文章之前希望大家先看一下这篇文章o(∩_∩) ...

  4. 总结Linux 下Redis 操作常用命令(转)

    Redis的配置 Linux下安装 ]# wget http://download.redis.io/releases/redis-2.8.17.tar.gz ]# tar xzf redis-2.8 ...

  5. 表格排序(tablesorter)

    1.在html页面的head中引用 <script src="/static/Bootstrap/js/jquery/jquery.tablesorter.min.js"&g ...

  6. rsync 数据同步

    什么是Rsync? Rsync是一款开源的.快速的.多功能的.可实现全量及增量的本地货远程数据同步备份的优秀工具.适用于unix/linux/windows等多种操作系统平台. Rsync具有可使本地 ...

  7. 几种模型文件(CDM、LDM、PDM、OOM、BPM)

    概念数据模型 (CDM): 帮助你分析信息系统的概念结构,识别主要实体.实体的属性及实体之间的联系.概念数据模型(CDM)比逻辑数据模型 (LDM)和物理数据模型(PDM)抽象.CDM 表现数据库的全 ...

  8. 乘风破浪:LeetCode真题_022_Generate Parentheses

    乘风破浪:LeetCode真题_022_Generate Parentheses 一.前言 关于括号的题目,我们已经遇到过了验证正确性的题目,现在让我们生成合法的括号列表,怎么办呢?想来想去还是递归比 ...

  9. 利用Chrome浏览器的开发者工具截取整个页面

    ①打开Chrome浏览器的开发者工具: 快捷键: command + Alt + I (Mac). Ctrl + shift + I (Windows) 或者: 鼠标右键 -> 弹出菜单中选择 ...

  10. skimage 安装和子模块

    平台:Windows 10 1.安装anaconda anaconda是python环境的集成安装软件,建议安装2.7版本的python 2.安装skimage 打开windows的命令提示符:  输 ...