前言

在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. 用jquery实现遮罩层

    <div style=" display:none" id="yinying"></div> <script type=" ...

  2. 其实Unix很简单

    很多编程的朋友都在网上问我这样的几个问题,Unix怎么学?Unix怎么这么难?如何才能学好?并且让我给他们一些学好Unix的经验.在绝大多数时候,我发现问这些问题的朋友都有两个特点: 1)对Unix有 ...

  3. android app自动化测试之UIAutomator

    一.UIAutomator Android自动化测试工具有很多,但是要免费.易上手,本人觉得就直接使用Eclipse自带的UIAutomator就不错.测试人员无需跟开发要代码信息,只要手机上有安装之 ...

  4. SharedPreferences写入和读出数据

    Android中有很多方法存储数据,如SharedPreferences.SQLite数据库等.简单数据的存储适用SharedPreferences. 本文使用SharedPreferences写入和 ...

  5. 【Java每日一题】20161102

    package Nov2016; public class Ques1102 implements Parent{ @Override public void method() { } } inter ...

  6. IOS 集成第三方登录

    我使用的是友盟上集成的第三方登录功能,一共使用了三个应用的登录授权,QQ.微信.新浪微博.由于第三方登录授权成功后,需要跳转到一个新的界面,所以这里需要在项目里设置第三方登录的SSO授权.就是必须安装 ...

  7. Scalaz(45)- concurrency :Task-函数式多线程编程核心配件

    我们在上一节讨论了scalaz Future,我们说它是一个不完善的类型,最起码没有完整的异常处理机制,只能用在构建类库之类的内部环境.如果scalaz在Future类定义中增加异常处理工具的话,用户 ...

  8. yii2 advance 安装

    1. 前提条件,php版本得> 5.4 D:\phpStudy>php -v PHP (cli) (built: Sep ::) Copyright (c) - The PHP Group ...

  9. Git远程和分支管理

    一.远程       Git是分布式版本控制系统,最重要的优点就是远程仓库托管代码.不用自己搭建一个服务器,在github上面注册一个账户就可免费获取远程仓库.      首先需要先在github上面 ...

  10. Exif.js 读取图像的元数据

    Exif.js 提供了 JavaScript 读取图像的原始数据的功能扩展,例如:拍照方向.相机设备型号.拍摄时间.ISO 感光度.GPS 地理位置等数据. 注意事项: EXIF 数据主要来自拍摄的照 ...