在Java中String类为什么要设计成final?String真的不可变吗?其他基本类型的包装类也是不可变的吗?

时间:2022-04-12 07:59:08

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

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

在Java中String类为什么要设计成final?String真的不可变吗?其他基本类型的包装类也是不可变的吗?

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

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

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

在Java中String类为什么要设计成final?String真的不可变吗?其他基本类型的包装类也是不可变的吗?

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

代码测试:

 String test = "immutable String";
String test1 = test;
String test2 = new String(test);
String test3 = new String(test.toCharArray());
Field values = String.class.getDeclaredField("value");
values.setAccessible(true);
char[] chars = (char[])values.get(test);
chars[] = 'u';
chars[] = 'n';
System.out.println("test==test1:" + (test == test1));
System.out.println("test==test2:" + (test == test2));
System.out.println("test1==test2:" + (test1 == test2));
System.out.println("test:" + test + " test1:" + test1 + " test2:" + test2 + " test3:" + test3);

在Java中String类为什么要设计成final?String真的不可变吗?其他基本类型的包装类也是不可变的吗?

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

在Java中String类为什么要设计成final?String真的不可变吗?其他基本类型的包装类也是不可变的吗?

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

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

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

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

在Java中String类为什么要设计成final?String真的不可变吗?其他基本类型的包装类也是不可变的吗?的更多相关文章

  1. 在java中String类为什么要设计成final

    在java中String类为什么要设计成final? - 胖胖的回答 - 知乎 https://www.zhihu.com/question/31345592/answer/114126087

  2. 在java中String类为什么要设计成final?

    大神链接:在java中String类为什么要设计成final? - 程序员 - 知乎 我进行了重新排版,并且更换了其中的一个例子,让我们更好理解. String很多实用的特性,比如说“不可变性”,是工 ...

  3. java中String类为什么要设计成final?

    1 将方法或类声明为final主要目的是:确保它们不会在子类中改变语义.String类是final类,这意味着不允许任何人定义String的子类. String基本约定中最重要的一条是immutabl ...

  4. 【笔记】在java中String类为什么要设计成final?

    部分内容转自知乎:https://www.zhihu.com/question/31345592 从自己的理解进行加工,压缩. String本质上是一个final类 public final clas ...

  5. Java中String类为什么被设计为final?

    Java中String类为什么被设计为final   首先,String是引用类型,也就是每个字符串都是一个String实例.通过源码可以看到String底层维护了一个byte数组:private f ...

  6. java里String类为何被设计为final

    前些天面试遇到一个非常难的关于String的问题,"String为何被设计为不可变的"?类似的问题也有"String为何被设计为final?"个人认为还是前面一 ...

  7. 【JAVA零基础入门系列】Day11 Java中的类和对象

    今天要说的是Java中两个非常重要的概念--类和对象. 什么是类,什么又是对象呢?类是对特定集合的概括描述,比如,人,这个类,外观特征上,有名字,有年龄,能说话,能吃饭等等,这是我们作为人类的相同特征 ...

  8. Java中的类反射

    一.反射的概念 : 反射的概念是由Smith在1982年首次提出的,主要是指程序可以访问.检测和修改它本身状态或行为的一种能力.这一概念的提出很快引发了计算机科学领域关于应用反射性的研究.它首先被程序 ...

  9. Java程序设计基础笔记 • 【第7章 Java中的类和对象】

    全部章节   >>>> 本章目录 7.1 理解类和对象 7.1.1 对象 7.1.2 抽象与类 7.1.3 类与对象的关系: 7.2 Java中的类和对象 7.2.1 类的定义 ...

随机推荐

  1. CentOS初始化Mysql5&period;7密码

    /etc/init.d/mysql stopmysqld_safe --user=mysql --skip-grant-tables --skip-networking &mysql -u r ...

  2. C&num;获取类以及类下的方法&lpar;用于Asp&period;Net MVC&rpar;

    在C#中,实现动态获取类和方法主要通过反射来实现,要引用System.Reflection. public ActionResult GetControllerAndAction() List< ...

  3. C&sol;C&plus;&plus; 获取汉字拼音首字母

    #include <stdint.h> #include <stdio.h> #include <ctype.h> #include <string.h&gt ...

  4. 《JavaScript高级程序设计》读书笔记 ---if语句

    if语句 大多数编程语言中最为常用的一个语句就是if 语句.以下是if 语句的语法:if (condition) statement1 else statement2其中的condition(条件)可 ...

  5. MySQL错误:2003-Can&&num;39&semi;t connect to MySQL server on &&num;39&semi;localhost&&num;39&semi;&lpar;10061 &quot&semi;unknown error&quot&semi;&rpar;

    今天数据库出了一点错误之后决定重装一下,结果卡在了一个问题上,连装了5遍,加上网上各种配置教程都没能结局,错误如下图所示: 最后忽然想到会不会是因为每一次卸载的时候没有彻底卸载干净,然后就彻彻底底卸载 ...

  6. Codeforces 1092C Prefixes and Suffixes(思维)

    题目链接:Prefixes and Suffixes 题意:给定未知字符串长度n,给出2n-2个字符串,其中n-1个为未知字符串的前缀(n-1个字符串长度从1到n-1),另外n-1个为未知字符串的后缀 ...

  7. Selenium自动化测试-进阶2-框架篇

    前面的文章已经讲述了 Selenium自动化的入门知识,不知道各位看官看懂没有,有不懂的请留言. 接下来,开始讲解 Selenium自动化测试进阶知识. 首先讲解:自动化测试的核心: 利用自动化程序代 ...

  8. js中实现截取数组的后几个元素作为一个新数组的方法

    有时候我们会遇到这种需求,截取数组中后5个元素作为一个新数组,且顺序不能变.数组中的slice()方法和splice()方法都可以实现这样的操作. const arr = [1,2,7,2,6,0,3 ...

  9. Java连接SqlServer2008数据库

    Java连接SqlServer2008数据库 首先下载JDBC:下载地址:http://www.microsoft.com/zh-cn/download/details.aspx?id=21599 下 ...

  10. YOLO object detection with OpenCV

    Click here to download the source code to this post. In this tutorial, you’ll learn how to use the Y ...