点击上方 好好学java ,选择 星标 公众号

重磅资讯、干货,第一时间送达
今日推荐:都说了多少遍,不要再学 JSP 了!个人原创100W+访问量博客:点击前往,查看更多

从哪看出来String类是不可变的?

public final class Stringimplements java.io.Serializable, Comparable<String>, CharSequence {/** The value is used for character storage. */private final char value[];
}

String类的值是保存在value数组中的,并且是被private final修饰的

  1. private修饰,表明外部的类是访问不到value的,同时子类也访问不到,当然String类不可能有子类,因为类被final修饰了

  2. final修饰,表明value的引用是不会被改变的,而value只会在String的构造函数中被初始化,而且并没有其他方法可以修改value数组中的值,保证了value的引用和值都不会发生变化

final关键字的作用有如下几种

  1. final修饰类时,表明这个类不能被继承

  2. final修饰方法,表明方法不能被重写

  3. final修饰变量,如果是基本数据类型的变量,则其数值一旦在初始化之后便不能改变;如果是对象类型的变量,只能保证它的引用不变,但对象的内容是可以改变的

在Java中数组也是对象,数组即使被final修饰,内容还是可以改变的

所以我们说String类是不可变的。

附上我历时三个月总结的 Java 面试 + Java 后端技术学习指南,笔者这几年及春招的总结,github 1.1k star,拿去不谢!

下载方式

1. 首先扫描下方二维码

2. 后台回复「Java面试」即可获取

而很多方法,如substring并不是在原来的String类上进行操作,而是生成了新的String类

public String substring(int beginIndex) {if (beginIndex < 0) {throw new StringIndexOutOfBoundsException(beginIndex);}int subLen = value.length - beginIndex;if (subLen < 0) {throw new StringIndexOutOfBoundsException(subLen);}return (beginIndex == 0) ? this : new String(value, beginIndex, subLen);
}

为什么String被设置为不可变的?

字符串常量池

字符串常量池可以节省大量的内存空间。如果String类可变就不可能有字符串常量池

字符串常量池放在哪?

jdk1.7之前的不讨论,从jdk1.7开始,字符串常量池就开始放在堆中,然后本文的所有内容都是基于jdk1.8的

下面这个代码还是经常被问到的

String str1 = "abc";
String str2 = "abc";
String str3 = new String("abc");
String str4 = new String("abc");
// true
System.out.println(str1 == str2);
// false
System.out.println(str1 == str3);
// false
System.out.println(str3 == str4);

内存中的结构如下其中常量池中存的是引用

解释一下上面代码的输出,Java中有2种创建字符串对象的方式

String str1 = "abc";
String str2 = "abc";
// true
System.out.println(str1 == str2);

采用字面值的方式创建一个字符串时,JVM首先会去字符串池中查找是否存在"abc"这个对象的引用

如果不存在,则在堆中创建"abc"这个对象,并将其引用添加到字符串常量池(实际上是将引用放到哈希表中),随后将引用赋给str1

如果存在,则不创建任何对象,直接将池中"abc"对象的引用返回,赋给str2。因为str1、str2指向同一个对象,所以结果为true。

String str3 = new String("abc");
String str4 = new String("abc");
// false
System.out.println(str3 == str4);

采用new关键字新建一个字符串对象时,JVM首先在字符串池中查找有没有"abc"这个字符串对象的引用

如果没有,则先在堆中创建一个"abc"字符串对象,并将引用添加到字符串常量池,随后将引用赋给str3

如果有,则不往池中放"abc"对象的引用,直接在堆中创建一个"abc"字符串对象,然后将引用赋给str4。这样,str4就指向了堆中创建的这个"abc"字符串对象;

因为str3和str4指向的是不同的字符串对象,结果为false。

缓存HashCode

String类在被创建的时候,hashcode就被缓存到hash成员变量中,因为String类是不可变的,所以hashcode是不会改变的。这样每次想使用hashcode的时候直接取就行了,而不用重新计算,提高了效率

public final class Stringimplements java.io.Serializable, Comparable<String>, CharSequence {/** Cache the hash code for the string */private int hash; // Default to 0}

可以用作HashMap的key

由于String类不可变的特性,所以经常被用作HashMap的key,如果String类是可变的,内容改变,hashCode也会改变,当根据这个key从HashMap中取的时候有可能取不到value,或者取到错的value

线程安全

不可变对象天生就是线程安全的,这样可以避免在多线程环境下对String做同步操作

最后,再附上我历时三个月总结的 Java 面试 + Java 后端技术学习指南,笔者这几年及春招的总结,github 1.1k star,拿去不谢!

下载方式

1. 首先扫描下方二维码

2. 后台回复「Java面试」即可获取

String类为什么被设计为不可变的?相关推荐

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

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

  2. java string改变的影响_为什么Java的string类要设成immutable(不可变的)

    最流行的Java面试题之一就是:什么是不可变对象(immutable object),不可变对象有什么好处,在什么情况下应该用,或者更具体一些,Java的String类为什么要设成immutable类 ...

  3. java常用类-----String类的源码分析、可变和不可变序列

    package cn.zxg.PackgeUse; /** * 测试StringBuilder,StringBuffer可变字符序列 */ public class TestStringBuilder ...

  4. Java String类源码阅读笔记

    文章目录 一.前置 二.String类源码解析 1.String类继承关系 2.成员变量 3.构造方法 4.长度/判空 5.取字符 6.比较 7.包含 8.hashCode 9.查询索引 10.获取子 ...

  5. JAVA中String类

    1.String类定义的变量是不可变得 eg:String s0="kvill"; String s1 = new String("kvill"); 为什么要设 ...

  6. STL 的string类怎么啦?

    STL 的string类怎么啦? 陈皓 前言 上个周末在和我的同学爬香山闲聊时,同学说到STL中的string类曾经让他备受折磨,几年前他开发一个系统前对string类还比较清楚,然后随着程序的复杂度 ...

  7. Java中的String类

    首先String对象的内容是不可变的,也就是说,String对象在创建出来以后,其中的内容就不可改变了. 1.int length():这个方法用来返回字符串的长度,` String str=&quo ...

  8. String类详解(一)

    文章目录 1. 常见的构造String的方式 2. String类的不可变性 3. 修改字符串的方法 3.1 借助原字符串,创建新的字符串 3.2 使用StringBuilder类修改字符 3.3使用 ...

  9. c++ - 第8节 - string类

    目录 1.为什么学习string类 1.1.C语言中的字符串 1.2.面试题需要 2.标准库中的string类 2.1.string类 2.2.string类的常用接口说明 2.3.string类练习 ...

最新文章

  1. Java程序员需要熟悉的库
  2. csg显示寻找专用服务器失败,支持邻近发现过程的方法和装置
  3. 在阿里云服务器上安装docker
  4. python中装饰器的参数与返回值
  5. Npm常用命令有哪些
  6. 【软考】算法与数据结构复习指南
  7. dijkstra--非负权值的单源最短路径STL实现(邻接表+优先队列) (带路径)
  8. 艾瑞咨询:即时通讯面临多种安全威胁
  9. 46. 考虑使用函数对象而不是函数作为STL算法的参数
  10. ora-01189故障解决办法
  11. oracle 12952错误,故障码P1295
  12. Eclipse设立编辑器为绿豆沙颜色
  13. 微博营销有什么优势与缺点?如何利用微博开展营销?
  14. 他被称为“中国杀毒软件之父”,没想到身患残疾,38岁才接触电脑!
  15. NX二次开发 使用了一个已删除或无效的类号
  16. 学习云计算前景如何?云计算成为获取人工智能主要途径
  17. 没有躲过的坑--string中的c_str()陷阱
  18. Android悬浮窗口开发
  19. 电脑外设(I/O)简介:键盘鼠标
  20. 脚本修改root密码和命令修改root密码

热门文章

  1. 第二十篇:定义一个整形变量
  2. 基于visual c++之windows核心编程代码分析(64)现有的exe文件中添加自己的代码
  3. RDA8955中碰到的问题
  4. 宏EXPORT_SYMBOL在内核中的作用
  5. Boost Asio总结(4) io_service
  6. C++ Primer 5th笔记(chap 16 模板和泛型编程)模板实参推断和引用
  7. [密码学] 双重与三重DES
  8. 数据结构--单向链表
  9. 计算机信息应用知识题库,计算机基础知识题库(含答案).doc
  10. wxWidgets学习 (2) -- 事件处理