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

java字符串是不可变的。不可变类只是一个不能修改实例的类。实例创建时所有的信息都被初始化,并且信息不能被修改。不可变类有许多优点。本文总结了字符串为什么被设计成不可变的原因。这说明在记忆的角度不变性的概念,同步和数据结构。

1.字符串池的要求:

字符串池(字符串特定池)是方法区域中的一个特殊存储区域。当创建字符串时,如果字符串已经存在于池中,则将返回现有字符串的引用,而不是创建新对象。

下面的代码只在堆中创建一个字符串对象:

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

如图所示:

如果字符串是可变的,用一个引用更改字符串将导致其他引用的值错误。

2.缓存Hashcode:

在Java中,字符串的Hashcode经常被用到。例如,在一个HashMap或HashSet。一成不变的保证hashcode永远是相同的所以它可以兑现,不用担心变化。这意味着,不需要计算hashCode每次使用它。这更有效。

在String类中,它有以下代码:

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

3.经常使用其他对象:

为了说明这个问题,考虑下面的程序:

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";

在这个例子中,如果字符串是可变的,它的值是可以改变的,将违反设计集(包含非重复元素)。当然,上面的示例仅用于演示目的,在真正的字符串类中没有值字段。

4.安全:

字符串被广泛用于许多java类的参数,如网络连接、打开文件、字符串等都不是一成不变的,一个连接或文件将被改变,这可能导致严重的安全威胁。方法认为它是连接到一台机器,但不是。可变字符串也可能导致反射中的安全问题,因为参数是字符串。

代码如下:

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);
}

5.不可变对象自然是线程安全的:

因为不可变对象不能更改,所以可以在多个线程之间自由共享。这消除了进行同步的要求。

总之,字符串是为了效率和安全原因而不可变的。这也是为什么在很多情况下首选类是不可变类的原因。

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

  1. 图说:为什么Java中的字符串被定义为不可变的

    8张图,看懂Java字符串的不变性 字符串,想必大家最熟悉不过了,通常我们在代码中有几种方式可以创建字符串,比如:String s = "Hollis";这时,其实会在堆内存中创建 ...

  2. Java中的字符串常量池

    ava中字符串对象创建有两种形式,一种为字面量形式,如String str = "droid";,另一种就是使用new这种标准的构造对象的方法,如String str = new ...

  3. 理解Java中的字符串类型

    1.Java内置对字符串的支持: 所谓的内置支持,即不用像C语言通过char指针实现字符串类型,并且Java的字符串编码是符合Unicode编码标准,这也意味着不用像C++那样通过使用string和w ...

  4. java中String类为什么不可变?

    在面试中经常遇到这样的问题:1.什么是不可变对象.不可变对象有什么好处.在什么情景下使用它,或者更具体一点,java的String类为什么要设置成不可变类型? 1.不可变对象,顾名思义就是创建后的对象 ...

  5. 转载:Java中的字符串常量池详细介绍

    引用自:http://blog.csdn.net/langhong8/article/details/50938041 这篇文章主要介绍了Java中的字符串常量池详细介绍,JVM为了减少字符串对象的重 ...

  6. 《Java入门第三季》第二章 认识 Java 中的字符串

    什么是 Java 中的字符串.1.在Java的世界里,字符串被作为String类型的对象处理. 2.通用的初始化的方式:String s = new String("i love you & ...

  7. Java中的字符串常量池和JVM运行时数据区的相关概念

    什么是字符串常量池 JVM为了减少字符串对象的重复创建,其维护了一个特殊的内存,这段内存被成为字符串常量池或者字符串字面量池 工作原理 当代码中出现字面量形式创建字符串对象时,JVM首先会对这个字面量 ...

  8. Java中的字符串常量池,栈和堆的概念

    问题:String str = new String(“abc”),“abc”在内存中是怎么分配的?    答案是:堆内存.(Tips:jdk1.8 已经将字符串常量池放在堆内存区) 题目考查的为Ja ...

  9. Java中的字符串操作(比较String,StringBuiler和StringBuffer)

    一.前言 刚开始学习Java时,作为只会C语言的小白,就为其中的字符串操作而感到震撼.相比之下,C语言在字节数组中保存一个结尾的\0去表示字符串,想实现字符串拼接,还需要调用strcpy库函数或者自己 ...

随机推荐

  1. IntelliJ IDEA安装MongoDB的的数据操作插件

    说明:只能说效果一般,没有Robo 3T那么好用. 参考: https://intellij-support.jetbrains.com/hc/en-us/community/posts/206635 ...

  2. android wifi 调试

    (一)root你的Android(相信绝大多数人现在的手机已经ROOT了.(二)下载app: adbWireless,并安装到手机上.(三)安装adb工具包,其实,要在windows下使用ADB工具, ...

  3. ThinkPHP示例:CURD

    完整的控制器文件: class IndexAction extends Action { // 查询数据 public function index() { $Form = M("Form& ...

  4. 查找python项目依赖并生成requirements.txt

    1.如果使用virtualenv环境,直接使用 pip freeze > requirements.txt ➜  ~ .virtualenvs/xxx/bin/pip freeze > r ...

  5. ASP.NET Web API是如何根据请求选择Action的?[上篇] 【转】

    http://www.cnblogs.com/leo_wl/p/3316548.html ASP.NET Web API是如何根据请求选择Action的?[上篇] Web API的调用请求总是针对定义 ...

  6. NormalMap 贴图 [转]

    转载: http://www.zwqxin.com/archives/shaderglsl/review-normal-map-bump-map.html   说起Normal Map(法线贴图),就 ...

  7. js 动态获取对象多级属性

    var obj={ f1:{f2:{f3:2}} } var key="f1.f2.f3" var value=eval("obj."+key); consol ...

  8. nginx apache防盗链

    要实现防盗链,我们就必须先理解盗链的实现原理,提到防盗链的实现原理就不得不从HTTP协议说起,在HTTP协议中,有一个表头字段叫referer,采用URL的格式来表示从哪儿链接到当前的网页或文件.换句 ...

  9. VueJS循环语句:v-for

    v-for 指令需要以 item in items 形式的特殊语法, items 是源数据数组并且 item 是数组元素迭代的别名. HTML <!DOCTYPE html> <ht ...

  10. ThinkPHP中的模型命名

    当我们创建一个UserModel类的时候,其实已经遵循了系统的约定.ThinkPHP要求数据库的表名和模型类的命名遵循一定的规范,首先数据库的表名和字段全部采用小写形式,模型类的命名规则是除去表前缀的 ...