zoukankan      html  css  js  c++  java
  • 在Java中String类为什么要设计成final?String真的不可变吗?其他基本类型的包装类也是不可变的吗?

    最近突然被问到String为什么被设计为不可变,当时有点懵,这个问题一直像bug一样存在,竟然没有发现,没有思考到,在此总结一下。

    1.String的不可变
    String类被final修饰,是不可继承和修改的。当一个String变量被第二次赋值时,不是在原有内存地址上修改数据,而是在内存中重新开辟一块内存地址,并指向新地址。

    String类为什么要被设计为是final的?

      1.不可变性支持线程安全
      2.不可变性支持字符串常量池,提升性能
      3.String字符串作为最常用数据类型之一,不可变防止了随意修改,保证了数据的安全性

    正常情况下Java的String字符串是final且不可变的。不过可以通过特殊手段修改它的内容。
    String类的主力成员字段value是个char[ ]数组,而且是用final修饰的。final修饰的字段创建以后就不可改变。因为虽然value是不可变,也只是value这个引用地址不可变。挡不住Array数组是可变的事实。Array的数据结构看下图:

    也就是说Array变量只是stack上的一个引用,数组的本体结构在heap堆。String类里的value用final修饰,只是说stack里的这个叫value的引用地址不可变。没有说堆里array本身数据不可变。

    代码测试:

     1 String test = "immutable String";
     2 String test1 = test;
     3 String test2 = new String(test);
     4 String test3 = new String(test.toCharArray());
     5 Field values = String.class.getDeclaredField("value");
     6 values.setAccessible(true);
     7 char[] chars = (char[])values.get(test);
     8 chars[0] = 'u';
     9 chars[1] = 'n';
    10 System.out.println("test==test1:" + (test == test1));
    11 System.out.println("test==test2:" + (test == test2));
    12 System.out.println("test1==test2:" + (test1 == test2));
    13 System.out.println("test:" + test + "   test1:" + test1 + " test2:" + test2 + "  test3:" + test3);

    由String的不可变性引申到其他基本数据类型: Byte,Short,Integer,Long,Double,Float,Character,Boolean 八种基本数据的包装类,仔细查看发现也是final修饰的,再仔细查看一下enum枚举类型,发现用javac编译后再用javap反编译也是被编译为final修饰的类,并且其枚举值全部定义为static final 修饰的成员变量。

    由此发现,Java设计者在设计Java基本数据类型时,把基本数据类型全部设计为不可变的,这样既方便了开发人员,又保证了数据的安全性。

    总结:Java中String是不可变的,但是可以通过反射修改其内容

    备注:
    作者:Shengming Zeng
    博客:http://www.cnblogs.com/zengming/ 

    本文是原创,欢迎大家转载;但转载时必须注明文章来源,且在文章开头明显处给明链接。
    <欢迎有不同想法或见解的同学一起探讨,共同进步>

  • 相关阅读:
    状态模式
    简单密码再次加密
    服务层定义自己的服务异常类
    必备网络基础知识(持续补充)
    MongoDB基础入门
    Git命令整理
    算法基础(四)
    RabbitMQ消息队列
    设计模式(23种)
    二叉树知识点
  • 原文地址:https://www.cnblogs.com/zengming/p/9367088.html
Copyright © 2011-2022 走看看