首页 > Java, 挨踢(IT) > 简易Java(08):为什么Java中的字符串是不可变的?

简易Java(08):为什么Java中的字符串是不可变的?

2014年5月23日 发表评论 阅读评论 978 人阅读    

“图解Java字符串的不可变性”中,介绍了在Java中字符串是不可改变的。但是,大家有没有想过“为什么字符串是不可变的?”今天就来给大家解释一下这个问题。

通过substring()方法在JDK6和JDK7中的异同 ”这篇文章,让D瓜哥看到,对于字符串的处理也是与时俱进。所以,如果发现下文中如有已经过时之处,请及时指出。D瓜哥也会及时更正的。

这是面试中经常被问到的老问题了。在Java中,将字符串设计成不可变是又很多原因的。一个好的回答需要建立在对内存、同步、数据结构等知识的深入理解之上的。下面,D瓜哥将给大家总结一下这方面的回答。

1、字符串常量池的需求

字符串常量池是Java虚拟机运行时的方法区中的一块特殊存储区域。当一个字符串被创建时,如果这个字符串已经在字符串常量池中存在,那么将直接返回这个已经存在的常量的引用,来代替创意一个新的对象并返回引用。

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

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

字符串常量池

如果字符串不是不可变,那么改变其中一个应用指向的字符串将导致另外一个引用所指向错误的值。

2、允许字符串缓存它的哈希值

在Java中,字符串的哈希值会经常用到。例如,在HashMap中。不变形保证字符串的哈希值总是一样的,所以,可以缓存起来而不用担心发现变化。换句话说,并不是每次调用都需要计算哈希值。这样会更有效。

String类中,有如下代码。

/** Cache the hash code for the string */
private int hash; // Default to 0

3、安全性

字符串作为类的参数,被广泛应用于Java很多很多类中。例如,网络连接(network connecton)、打开的文件等等。如果字符串不是不可变的,一个连接或者文件将可能会被改变,从而导致严重的安全问题。方法以为它已经连接到一个机器上,但事实上却没有。在反射(Reflection)中,可变的字符串也可能导致安全问题,例如字符串参数。

下面给出一个示例代码:

/**
 * Coder: D瓜哥,http://www.diguage.com/
 */

boolean connect(String s) {
    if (!isSecure(s)) {
        throw new SecurityException();
    }

    // 这里,如果 s 在此之前,被其他引用改变,那么将会触发问题。
    causeProblem(s);
}

总之,具体的原因包含设计、效率以及安全方面的考虑。实际上,这些方面也是很多Java面试题中需要考虑的方面。

《Simple Java》是一本讲解Java面试题的书。讲解也有不少独特之处,为了面试,《简易Java》走起!



作 者: D瓜哥,https://www.diguage.com/
原文链接:https://wordpress.diguage.com/archives/95.html
版权声明:非特殊声明均为本站原创作品,转载时请注明作者和原文链接。

  1. 本文目前尚无任何 trackbacks 和 pingbacks.