• 为什么Java中的String类是不可变的?


    String类是Java中的一个不可变类immutable class)。

    简单来说,不可变类就是实例在被创建之后不可修改。

    《Effective Java》 Item 15 中提到了为了使类成为不可变,需要遵循的五条规则:

    1. 不要提供任何会修改对象状态的方法。

    2. 保证类不会被扩展。

    3. 使所有的域都是final的。

    4. 使所有域都成为私有的。

    5. 确保对于任何可变组件的互斥访问。

    不可变类有许多优点,不可变类比可变类更加易于设计、实现和使用,不容易出错,且更加安全。

    下面来看一下Java把String类设计为不可变类的几个原因:

    1. 由于字符串池的存在

    字符串池(String Pool)是方法区中的一块存储空间,当创建一个字符串时,如果池中已经存在相同的字符串就会返回其引用,而不是在堆中创建一个新对象。(此处指的是字面量创建字符串,用new关键字创建的话,无论池中存不存在都会在堆中创建一个新对象)

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

    如果字符串是可变的话,通过一个引用改变它的值,将会导致其他引用的值也同样改变,从而可能发生错误。

    2. 缓存hashcode

    Java中经常用到一个字符串的hashcode,如在HashMap和HashSet中。不可变性保证同一个字符串对象的hashcode总是相同的,而在使用时不用考虑其是否发生改变。

    这意味着不需要每次都计算一遍hashcode,使程序更加高效。

    /** Cache the hash code for the string */
    private int hash; // Default to 0
    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";

     在这个例子中,如果String是可变的话将破坏HashSet(集合中可能会包含重复元素)。

    4. 安全性

    在Java中String被用作许多方法的参数,例如网络连接,对文件的操作等等。

    假如String不是不可变的,一个连接或文件将可能被改变,这会产生严重的安全隐患。

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

    不可变对象是线程安全的,它们可以被自由地共享,不要求同步。

    不可变类的优势有很多,当然也有缺点,就是对于每个不同的值都需要一个单独的对象。


    转载请注明原文链接:http://www.cnblogs.com/justcooooode/p/7514863.html

     参考资料

    《Effective Java》Item 15

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

  • 相关阅读:
    使用 Nginx 内置 $http_user_agent 来区分( 电脑 pc、手机 mobile、平板 pad )端的内容访问
    原创《开源一个用 vue 写的树层级组件 vue-ztree》
    原创《weex面向未来的架构》
    原创《如何用vue来轻松的驾驭 html5 webapp的页面体验》
    Pdf Convert Image 的解决方案
    原创《分享(Angular 和 Vue)按需加载的项目实践优化方案》
    .npmrc 实用小技巧
    使用Tampermonkey,实现Gitlab禁用自我Merge的功能
    vue 之 render 函数不能渲染非全局自定义函数-方案
    反射、注解和动态代理
  • 原文地址:https://www.cnblogs.com/justcooooode/p/7514863.html
Copyright © 2020-2023  润新知