精华内容
下载资源
问答
  • 这样的设计也有很多优点,本文从内存、同步和数据结构方面总结了为什么String设计成不可变的原因。1、字符串常量池的需要字符串常量池是一个特殊的存储区域。当创建字符串时,如果字符串已经存在于池中,则将返

    原文来自:Why String is immutable in Java?

    这是来自Java和Android面试中经常被问的一道题目。在Java语言中,String是字符串常量,StringBuilder是字符串变量,为什么将String设计成不可变的(immutable)?

    在Java里String类是不可变的,不可变类是一个不能被修改实例的类,实例创建时所有的信息都被初始化,并且不可被修改。这样的设计也有很多优点,本文从内存、同步和数据结构方面总结了为什么把String类设计成不可变的原因。

    1、字符串常量池的需要

    字符串常量池是一个特殊的存储区域。当创建字符串时,如果字符串已经存在于池中,则将返回现有字符串的引用,而不会创建新的对象。
    下面的代码只在堆中创建一个字符串对象:

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

    示意图如下:
    这里写图片描述
    如果String是可变的,用一个引用改变字符串将导致其他引用的值错误。

    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、不可变对象自然是线程安全的

    因为不可变对象是不能被改变的,所以他们可以自由的共享多线程。这就消除了他们进行同步的要求。

    总结

    总之,String被设计成不可变的是出于效率和安全的因素。这也是为什么很多情况下首选类是不可变类的原因。

    当然,不同的使用场景体现出不可变特性的优势也不相同。大家可以回忆自己项目中的使用场景,多加思考这类问题。

    展开全文
  • 为什么String在 java 中是不可变的? 这是一个受欢迎的面试问题。 字符串是任何编程语言中使用最多的类之一。 我们知道 String 在 java 和 java 运行时是不可变(immutable )和最终(final)的,使用 String pool来维护,...

    为什么String在 java 中是不可变的? 这是一个受欢迎的面试问题。 字符串是任何编程语言中使用最多的类之一。 我们知道 String 在 java 和 java 运行时是不可变(immutable )和最终(final)的,使用 String pool来维护,使它成为一个特殊类。


    让我们来看看字符串不可变性的一些好处,这些好处有助于我们来理解为什么 String 在 java 中是不可变的:

    • 1.由于 String 在 Java 中是不可变的,这样 Java Runtime 就可以节省大量的 Java 堆空间,因为不同的 String 变量可以在String Pool中引用相同的 String 变量(实际String对象的值)。
    • 2.如果String不是不可变的,那么它将对应用程序造成严重的安全威胁。 例如,数据库用户名,密码作为String传递以获取数据库连接.如果String是可变的,黑客可以轻松改变它的引用值以导致应用程序中出现安全问题。
    • 3.由于String是不可变的,所以它在多线程环境(multithreading)是线程安全的,一个 String 实例可以在不同的线程中共享。 这避免了使用同步(synchronization)来保护线程安全,String是隐式线程安全的.
    • 4.String被用在了classloader 类加载器中,不可变性提供了正确的类由Classloader加载的安全性。 例如,假设您尝试加载java.sql.Connection类的实例,但引用的值更改为myhacked.Connection类,可以对数据库执行有害的操作。
    • 5.由于 String 是不可变的,它的 hashcode 在创建时就被缓存了,它不需要再次计算,并且它的处理速度比其他 Object对象要快。这也是为什么 HashMap 常用 String 对象作 key的原因

    引申阅读: 如何设计一个不可变类(immutable class)?

    展开全文
  • 在Java中将String设计成不可变的是综合考虑到各种因素的结果,想要理解这个问题,需要综合内存,同步,数据结构以及安全等方面的考虑. 在下文中,我将各种原因做一个小结。 1. 字符串常量池的需要 字符串常量...

    这是一个老生常谈的话题(This is an old yet still popular question). 在Java中将String设计成不可变的是综合考虑到各种因素的结果,想要理解这个问题,需要综合内存,同步,数据结构以及安全等方面的考虑. 在下文中,我将为各种原因做一个小结。

    1. 字符串常量池的需要

    字符串常量池(String pool, String intern pool, String保留池) 是Java堆内存中一个特殊的存储区域, 当创建一个String对象时,假如此字符串值已经存在于常量池中,则不会创建一个新的对象,而是引用已经存在的对象。

    如下面的代码所示,将会在堆内存中只创建一个实际String对象.

    [java] view plain copy
    1. String s1 = "abcd";  
    2. String s2 = "abcd";  
    示意图如下所示:

    图1

    假若字符串对象允许改变,那么将会导致各种逻辑错误,比如改变一个对象会影响到另一个独立对象. 严格来说,这种常量池的思想,是一种优化手段.

    思考: 假若代码如下所示,s1和s2还会指向同一个实际的String对象吗?

    [javascript] view plain copy
    1. String s1= "ab" + "cd";  
    2. String s2= "abc" + "d";  
    也许这个问题违反新手的直觉, 但是考虑到现代编译器会进行常规的优化, 所以他们都会指向常量池中的同一个对象. 或者,你可以用 jd-gui 之类的工具查看一下编译后的class文件.

    2. 允许String对象缓存HashCode
    Java中String对象的哈希码被频繁地使用, 比如在hashMap 等容器中。

    字符串不变性保证了hash码的唯一性,因此可以放心地进行缓存.这也是一种性能优化手段,意味着不必每次都去计算新的哈希码. 在String类的定义中有如下代码:

    [javascript] view plain copy
    1. private int hash;//用来缓存HashCode  
    3. 安全性
    String被许多的Java类(库)用来当做参数,例如 网络连接地址URL,文件路径path,还有反射机制所需要的String参数等, 假若String不是固定不变的,将会引起各种安全隐患。

    假如有如下的代码:

    [javascript] view plain copy
    1. boolean connect(string s){  
    2.     if (!isSecure(s)) {   
    3. throw new SecurityException();   
    4. }  
    5.     // 如果在其他地方可以修改String,那么此处就会引起各种预料不到的问题/错误   
    6.     causeProblem(s);  
    7. }  


    总体来说, String不可变的原因包括 设计考虑,效率优化问题,以及安全性这三大方面. 事实上,这也是Java面试中的许多 "为什么" 的答案。
    展开全文
  • 为什么String设计成不可变

    千次阅读 2018-08-16 22:11:22
    在Java中将String设计成不可变的是综合考虑到各种因素的结果,想要理解这个问题,需要综合内存,同步,数据结构以及安全等方面的考虑. 在下文中,我将各种原因做一个小结。 1. 字符串常量池的需要 字符串常量池...

         在Java中将String设计成不可变的是综合考虑到各种因素的结果,想要理解这个问题,需要综合内存,同步,数据结构以及安全等方面的考虑. 在下文中,我将为各种原因做一个小结。

    1. 字符串常量池的需要

    字符串常量池(String pool, String intern pool, String保留池) 是Java堆内存中一个特殊的存储区域, 当创建一个String对象时,假如此字符串值已经存在于常量池中,则不会创建一个新的对象,而是引用已经存在的对象。

    如下面的代码所示,将会在堆内存中只创建一个实际String对象.

    String s1="abc";
    String s2="abc";

    假若字符串对象允许改变,那么将会导致各种逻辑错误,比如改变一个对象会影响到另一个独立对象. 严格来说,这种常量池的思想,是一种优化手段.

    思考: 假若代码如下所示,s1和s2还会指向同一个实际的String对象吗?

    String s1="abc";
    String s2="ab"+"c";

    答案是肯定的,现代编译器会进行常规的优化, 所以他们都会指向常量池中的同一个对象。

    2.允许String对象缓存HashCode
    Java中String对象的哈希码被频繁地使用, 比如在hashMap 等容器中。

    字符串不变性保证了hash码的唯一性,因此可以放心地进行缓存.这也是一种性能优化手段,意味着不必每次都去计算新的哈希码. 在String类的定义中有如下代码:

    3.安全性

    String被许多的Java类(库)用来当做参数,例如 网络连接地址URL,文件路径path,还有反射机制所需要的String参数等, 假若String不是固定不变的,将会引起各种安全隐患。

    4.总结

    String不可变的原因包括 设计考虑,效率优化问题,以及安全性这三大方面. 

     

    展开全文
  • 在Java中将String设计成不可变的是综合考虑到各种因素的结果,想要理解这个问题,需要综合内存,同步,数据结构以及安全等方面的考虑. 在下文中,我将各种原因做一个小结。 1. 字符串常量池的需要 字符串常量池...
  • 我们来分析下为什么Java中String设计成不可变的。 首先我们来看一段代码: public class Test { public static void main(String []args) { String s1 = "abcdef"; System.out.println(s1); ...
  • 字符串池 字符串池是方法区中的一部分特殊存储。当一个字符串被被创建的时候,首先会去这个字符串池中查找,...如果字符串可变的话,当两个引用指向指向同一个字符串时,对其中一个做修改就会影响另外一个。(请记...
  • 为什么String设计成不可变

    千次阅读 2018-07-19 10:13:49
    String的构成 1public final class String 2 implements java.io.Serializable, Comparable&lt;String&gt;, CharSequence { 3 /** The value is used for character storage. */ 4 ...
  • String是Java中最常用的类,是不可变的(Immutable), 那么String是如何实现Immutable呢,String为什么设计成不可变呢? 前言 关于String,收集一波基础,来源标明最后,不确定是否权威, 希望有问题可以得到纠正。 0....
  • String为什么设计成不可变的? 1、字符串池的需求字符串池是方法区(Method Area)中的一块特殊的存储区域。当一个字符串已经被创建并且该字符串在 池 中,该字符串的引用会立即返回给变量,而不是重新创建一个...
  • String不可变String值储存在常量池中。...为什么不可变 String 类本身是final的,不可以被继承 String类内部通过private final char value[]实现,从而保证了引用的不可变和对外的不可见 Stri...
  • 这几天在各大平台上都看到过这样一些帖子,全都是关于String类型对象不可变的问题,当然现在也是找工作的准备时期,因此花了一部分...(4)JAVA语言为什么String类型设计成不可变?带着这些问题就可以开始今天的文章...
  • 最流行的Java面试题之一就是:什么是不可变对象(immutable object),不可变对象有什么好处,在什么情况下应该用,或者更具体一些,Java的String为什么要设immutable类型? 不可变对象,顾名思义就是创建后不可以...

空空如也

空空如也

1 2 3 4 5 ... 16
收藏数 305
精华内容 122
关键字:

为什么string设计成不可变