Java全栈知识(2)String类String常量池
创始人
2025-05-30 22:06:55
0

1、String类的不可变性

我们打开源码

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

String对象里面的字符串其实就是存放在一个char[]类型的数组中,该数组是由final修饰的,并且没有提供任何的set方法共给用户使用,也就是说String类是不可变的。这样做有什么好处呢?

1、String的hash值经常被使用

我们经常使用String类型的字符串作为Hashmap的key,此时的hash值使用的就是String类中的存储hash的成员变量里面的值,而String里面的hash属性是通过第一次调用hashCode()方法计算出来存到属性中的。

2、字符串常量池的需要

如果一个 String 对象已经被创建过了,那么就会从 String Pool 中取得引用。只有 String 是不可变的,才可能使用 String Pool。

3、线程安全

因为Sting不可变,自然不用担心线程安全的问题

2、String Pool

String Pool也叫字符串常量池,其本质上是维护在堆上的一张hash表。

如下:

public static void main(String[] args) {String s1 = "hello";String s2 = "hello";String s3 = new String("hello");String s4 = new String("hello");System.out.println(s1 == s2); // trueSystem.out.println(s1 == s3); // falseSystem.out.println(s3 == s4); // false
}

如果我们调用new String()方法是直接创建了一个新的String对象,所以两次创建的都是不同的对象,

但是如果我们直接String s1 = "hello"这样创建字符串,本质上是在字符串常量池中创建了一个“hello”这么一个String对象在String Pool中,再使s3指向常量池中的内容。所以s4和s3的内容其实都是String Pool中“hello”的引用。所以相等。

2.1、修改字符串

如果我们调用

String str1 = "hello";
str1+=" world";

其实在字符串常量池中是,创建了“ world”对象,并且重新创建了一个新的String对象,内容是“hello world”,然后改变了str1的指向,从而改变了str1中的值,原来的“hello”还在String Pool中,此时的StringPool中一共有三个对象“hello”“ world”“hello world”。后续无用的会被JVM回收

注意:

我们在开发中,应该避免出现下列代码

String str = "hello" ; 
for(int x = 0; x < 1000; x++) {str += x ; 
}
System.out.println(str);

因为会多次在String Pool创建中创建对象,影响效率。

2、Intern()方法

String str1 = new String("hello").intern() ; 
String str2 = "hello" ; 
System.out.println(str1 == str2); 
// 执行结果
true

调用intern的本质就是把该字符串放入到String Pool中。

2.3、HotSpot中字符串常量池保存哪里?永久代?方法区还是堆区?

  1. 运行时常量池(Runtime Constant Pool)是虚拟机规范中是方法区的一部分,在加载类和结构到虚拟机后,就会创建对应的运行时常量池;而字符串常量池是这个过程中常量字符串的存放位置。所以从这个角度,字符串常量池属于虚拟机规范中的方法区,它是一个逻辑上的概念;而堆区,永久代以及元空间是实际的存放位置。
  2. 不同的虚拟机对虚拟机的规范(比如方法区)是不一样的,只有 HotSpot 才有永久代的概念。
  3. HotSpot也是发展的,由于一些问题的存在,HotSpot考虑逐渐去永久代,对于不同版本的JDK,实际的存储位置是有差异的,具体看如下表格:

JDK版本

是否有永久代,字符串常量池放在哪里?

方法区逻辑上规范,由哪些实际的部分实现的?

jdk1.6及之前

有永久代,运行时常量池(包括字符串常量池),静态变量存放在永久代上

这个时期方法区在HotSpot中是由永久代来实现的,以至于这个时期说方法区就是指永久代

jdk1.7

有永久代,但已经逐步“去永久代”,字符串常量池、静态变量移除,保存在堆中;

这个时期方法区在HotSpot中由永久代(类型信息、字段、方法、常量)和(字符串常量池、静态变量)共同实现

jdk1.8及之后

取消永久代,类型信息、字段、方法、常量保存在本地内存的元空间,但字符串常量池、静态变量仍在堆中

这个时期方法区在HotSpot中由本地内存的元空间(类型信息、字段、方法、常量)和(字符串常量池、静态变量)共同实现

相关内容

热门资讯

linux入门---制作进度条 了解缓冲区 我们首先来看看下面的操作: 我们首先创建了一个文件并在这个文件里面添加了...
C++ 机房预约系统(六):学... 8、 学生模块 8.1 学生子菜单、登录和注销 实现步骤: 在Student.cpp的...
JAVA多线程知识整理 Java多线程基础 线程的创建和启动 继承Thread类来创建并启动 自定义Thread类的子类&#...
【洛谷 P1090】[NOIP... [NOIP2004 提高组] 合并果子 / [USACO06NOV] Fence Repair G ...
国民技术LPUART介绍 低功耗通用异步接收器(LPUART) 简介 低功耗通用异步收发器...
城乡供水一体化平台-助力乡村振... 城乡供水一体化管理系统建设方案 城乡供水一体化管理系统是运用云计算、大数据等信息化手段࿰...
程序的循环结构和random库...   第三个参数就是步长     引入文件时记得指明字符格式,否则读入不了 ...
中国版ChatGPT在哪些方面... 目录 一、中国巨大的市场需求 二、中国企业加速创新 三、中国的人工智能发展 四、企业愿景的推进 五、...
报名开启 | 共赴一场 Flu... 2023 年 1 月 25 日,Flutter Forward 大会在肯尼亚首都内罗毕...
汇编00-MASM 和 Vis... Qt源码解析 索引 汇编逆向--- MASM 和 Visual Studio入门 前提知识ÿ...
【简陋Web应用3】实现人脸比... 文章目录🍉 前情提要🌷 效果演示🥝 实现过程1. u...
前缀和与对数器与二分法 1. 前缀和 假设有一个数组,我们想大量频繁的去访问L到R这个区间的和,...
windows安装JDK步骤 一、 下载JDK安装包 下载地址:https://www.oracle.com/jav...
分治法实现合并排序(归并排序)... 🎊【数据结构与算法】专题正在持续更新中,各种数据结构的创建原理与运用✨...
在linux上安装配置node... 目录前言1,关于nodejs2,配置环境变量3,总结 前言...
Linux学习之端口、网络协议... 端口:设备与外界通讯交流的出口 网络协议:   网络协议是指计算机通信网...
Linux内核进程管理并发同步... 并发同步并发 是指在某一时间段内能够处理多个任务的能力,而 并行 是指同一时间能够处理...
opencv学习-HOG LO... 目录1. HOG(Histogram of Oriented Gradients,方向梯度直方图)1...
EEG微状态的功能意义 导读大脑的瞬时全局功能状态反映在其电场结构上。聚类分析方法一致地提取了四种头表面脑电场结构ÿ...
【Unity 手写PBR】Bu... 写在前面 前期积累: GAMES101作业7提高-实现微表面模型你需要了解的知识 【技...