前言

在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#】递归搜索指定目录下的指定项目(文件或目录)

    ---------------更新:201411201121--------------- 主要更新说明:将原bool recurse参数改为int depth,这样可以指定递归深度,而不是笼统的是否 ...

  2. C#操作 word代码

    #region 读取word /// <summary> /// 读取word所有文字内容(不包含表格) /// </summary> /// <returns>w ...

  3. linq 实现动态 orderby

    class Pet { public string Name{get;set;} public int Age{get;set;} } void Main() { Pet[] pets = { }, ...

  4. 更改(修改)mysql自动增序列改变从1000开始

    更改(修改)mysql自动增序列改变从1000开始 ************************************************************************** ...

  5. 根据商品名称、价格区间检索商品的SQL语句

    如果名称和价格为空会检索出所有的数据 select * from TblProduct where (@proName='' or chvProName like '%'+@proName+'%') ...

  6. ubuntu下golang环境配置

    安装go 可以到Golang中国下载go的安装包 解压安装包tar -C /usr/local -xzf <安装包> 添加环境变量`export PATH=$PATH:/usr/local ...

  7. GC之详解CMS收集过程和日志分析

    2016-08-23   关于GC的算法和垃圾收集器的种类就暂且不说了,网上有大把的资料供参考 话题引入 让我们先简单的看下整个堆年轻代和年老代的垃圾收集器组合(以下配合java8完美支持,其他版本可 ...

  8. 【转】推荐介绍几款小巧的Web Server程序

    原博地址:http://blog.csdn.net/heiyeshuwu/article/details/1753900 偶然看到几个小巧有趣的Web Server程序,觉得有必要拿来分享一下,让大家 ...

  9. UML类图关系总结

    在UML类图中,常见的有以下几种关系: 泛化(Generalization) 实现(Realization) 关联(Association) 聚合(Aggregation) 组合(Compositio ...

  10. Tomcat部署记事

    1.导入证书到jdk里 keytool -import -alias 证书名称 -file 证书地址 -keystore 导入位置 例:keytool -import -alias co3 -file ...