前言

在Java中,字符串是一个不可变的类,一个不可变的类指的是它的实例对象不能被修改,所有关于这个对象的信息在这个对象被创建时已初始化且不能被改变。

不可变类有很多优势,这篇文章总结了字符串类之所以被设计成不可变类的原因,涉及内存模型,线程同步,数据结构等知识。

字符串常量池的需求

字符串常量池是方法区中的一块特别存储区域。当需要创建一个字符串时,如果它的值在字符串常量池中已存在,那么常量池中的该字符串引用将被直接返回,而不会创建一个新的字符串对象返回其引用。

String string1 = "abcd";
String string2 = "abcd";

如果字符串是可变的,那么通过一个引用改变字符串的值,其它该字符串对象的引用将得到错误的值。

缓存Hashcode

字符串的hashcode在java中经常被使用,如HashMap。不可变保证了hashcode会一直相同,所以它可以缓存起来而不需要担心改变。这也意味着,每次使用String的时候,不需要重新计算hashcode,这使得性能更加有效,所以我们经常会看到map的key使用字符串。

在String类中,有一个hash字段用于缓存hash code。

private int hash;//this is used to cache hash code.

方便其它对象的使用

为了更加具体的说明,看下下面的程序:

HashSet<String> set = new HashSet<String>();
set.add(new String("a"));
set.add(new String("b"));
set.add(new String("c"));
for(String a: set)
a.value = "a";

在这个例子中,如果字符串是可变的,那么它的value会被改变,这将违背Set集合的设计(不允许重复元素)。当然,这仅仅是一个示例,实际情况,String是没有value字段的。

安全性

字符串作为参数被广泛使用,如网络连接,文件打开操作等。如果字符串是可变的,那么网络连接或者文件将会被改变,这将引起严重的安全威胁。某个方法被认为连接到某一台机器,但是却被改变了,连接到其它机器。在反射中,可变的字符串同样会引起安全问题,因为参数同样是字符串。

如下代码是一个例子:

boolean connect(string s){
if (!isSecure(s)) {
throw new SecurityException();
   }
//here will cause problem, if s is changed before this by using other references.
causeProblem(s);
}

不可变的对象天生线程安全

因为不可变对象不能被修改,它们可以被多线程共享,这消除了同步操作。

总的来说,字符串被设计成不可变是出于性能和安全考虑,这也是为什么通常不可变类比较受欢迎。

译文链接:http://www.programcreek.com/2013/04/why-string-is-immutable-in-java/

为什么Java中字符串是不可变的的更多相关文章

  1. 三张图彻底了解Java中字符串的不变性

    转载: 三张图彻底了解Java中字符串的不变性 定义一个字符串 String s = "abcd"; s中保存了string对象的引用.下面的箭头可以理解为"存储他的引用 ...

  2. java中字符串的非空判断

    问题如下:在java 中 字符串为null 如何判断String str;if(str==null) ??str.equal("null") ?? 答:我觉得应该搞清楚字符串对象和 ...

  3. java中字符串String 转 int(转)

    java中字符串String 转 int String -> int s="12345"; int i; 第一种方法:i=Integer.parseInt(s); 第二种方法 ...

  4. 【转】Java中字符串中子串的查找共有四种方法(indexof())

    原文网址:http://wfly2004.blog.163.com/blog/static/1176427201032692927349/ Java中字符串中子串的查找共有四种方法,如下:1.int ...

  5. Java中字符串中子串的查找共有四种方法(indexof())

    Java中字符串中子串的查找共有四种方法(indexof()) Java中字符串中子串的查找共有四种方法,如下:1.int indexOf(String str) :返回第一次出现的指定子字符串在此字 ...

  6. JAVA中字符串函数subString的用法小结

    本篇文章主要是对JAVA中字符串函数subString的用法进行了详细的介绍,需要的朋友可以过来参考下,希望对大家有所帮助 String str; str=str.substring(int begi ...

  7. Java中字符串的一些常见方法

    1.Java中字符串的一些常见方法 /** * */ package com.you.model; /** * @author Administrator * @date 2014-02-24 */ ...

  8. Java中字符串indexof() 的使用方法

    Java中字符串中子串的查找共有四种方法(indexof())indexOf 方法返回一个整数值,指出 String 对象内子字符串的开始位置.如果没有找到子字符串,则返回-1.如果 startind ...

  9. Java中字符串string的数据类型

    Java中字符串string的数据类型 时间:2017-07-03 08:01:47 YuanMxy 原文:https://blog.csdn.net/YuanMxy/article/details/ ...

随机推荐

  1. C#多种方式获取文件路径

    string str5=Application.StartupPath;//获取启动了应用程序的可执行文件的路径,不包括可执行文件的名称. string str1 =Process.GetCurren ...

  2. javascript小数点后4舍5进

    toFixed();获得小数点后面多少为数字.四舍五入的方法. 例如: var floatNum = 5.234 var temp = floatNum.toFixed(1); -- temp = 5 ...

  3. 关于js性能

    1,声明变量要赋初值2,尽量避免声明全局变量,可以减少与系统的重名3,当编写大量js代码时,难免会遇到命名冲突,这是可以通过模拟命名空间方式     来避免冲突4,尽量避免使用全局变量,搜索全局变量是 ...

  4. jQuery漂亮图标的垂直导航菜单

    效果展示 http://hovertree.com/texiao/nav/3/ jQuery漂亮图标的垂直导航菜单 是一款当鼠标滑过菜单项时,会有一个背景遮罩层跟着鼠标移动,效果非常炫酷,图标还是矢量 ...

  5. 使用Aspose插件对Excel操作

    使用使用Aspose插件对Excel文档进行导入导出操作 使用前请先下载Aspose插件引用 Excel导入: 前台使用file标签获取,submit方式提交. <form id="f ...

  6. Debian 7 下安装CodeBlocks12.11

    1. 安装编译器 sudo apt-get install build-essential 2. 安装debug工具gdb sudo apt-get install gdb 3. 更新源 sudo n ...

  7. Time series database

    https://en.wikipedia.org/wiki/Time_series_database https://influxdb.com/docs/v0.9/introduction/getti ...

  8. 2016 年沈阳网络赛---QSC and Master(区间DP)

    题目链接 http://acm.hdu.edu.cn/showproblem.php?pid=5900 Problem Description Every school has some legend ...

  9. Ionic – 强大的 HTML5 Mobile App 开发框架

    Ionic 是一个强大的 HTML5 应用程序开发框架,可以帮助您使用 Web 技术,比如 HTML.CSS 和 Javascript 构建接近原生体验的移动应用程序.Ionic 主要关注外观和体验, ...

  10. WCF的三个名称/命名空间,你是否傻傻分不清楚?

    在定义和寄宿WCF服务的时候会面临三个名称/命名空间,它们分别是ServiceContractAttribute.ServiceBehaviorAttribute和Binding的Name和Names ...