JAVA中String的底层解析

2023-05-16

JAVA中String 是Final类不能被继承。JAVA 对String的处理和一般Class有所不同。
这文章主要是解释一下String的存储模式和java的字符串常量池的机制,和几个涉及底层的引用问题解析。

首先提出几个问题:
1.String的内容为什么是不可更改的?
2.JAVA中“adc”这种创建的字符串的创建过程是怎样的?
3.String(String string)的构造方法是如何工作的?
4.一个线程中内容为“adc”的String对象,存储的char[]是否是同一个,char[]数组是否一定在字符串常量池中?
5思考java中String 不可更改的好处在哪?
6 intern方法和字符串常量池的关系?
7string的+编译器是如何处理的?

1.String的内容为什么是不可更改的?
我们通过源代码可以看到存储string内容的char[]是这么定义的:

private final char value[];

可能有人会有疑问既然是final引用却没有附初始值。
答案是final变量是可以在构造方法中进行赋值的。
所以value的所有赋值都在String的几个构造方法中。
这样从代码逻辑上控制了String不可变。

2.JAVA中“adc”这种创建的字符串的创建过程是怎样的?

这个问题比较简单,就是”adc“会被放到字符串常量池中,可以称为字面量,所有String s=“adb” 的字符串的引用都是指向字符串常量池中的。

3.String(String string)的构造方法是如何工作的?

 public String(String original) {
        this.value = original.value;
        this.hash = original.hash;
    }

这说明从用String去new String构造新的对象是,确实会产生新的对象,而且新的value和hash值都和原String对象一致。
当然String还是有其他构造方法,都会去new char[]

4一个线程中内容为“adc”的String对象,存储的char[]是否是同一个,char[]数组是否一定在字符串常量池中?
答案其实可以根据3推导出。
由String产生的String里面的char[]是同一个,其他方式产生的都是新的。“”包裹产生的字符串会在常量池中,其他的都是正常的存在堆中。所以堆中可以有n份“adb”的串,常量池中的“adc”永远只有一个,可以被多个引用所指向。后续将会用代码解释上述所有现象。

public static void main(String[] args)
			throws NoSuchFieldException, SecurityException, IllegalArgumentException, IllegalAccessException {
		// TODO Auto-generated method stub

		String string = "abc";
		String string2 = "abc";
	    String string3 = new String(string);
	    char[] charString={'a','b','c'};
		String string4 = new String(charString);
		String string5 = new String(string4);
		
		charString[2]='e';
	
		Class sClass = String.class;
		Field privateStringField = sClass.getDeclaredField("value");
		privateStringField.setAccessible(true);
		char[] chars = (char[]) privateStringField.get(string);
		char[] chars2 = (char[]) privateStringField.get(string2);
		char[] chars3 = (char[]) privateStringField.get(string3);
		char[] chars4 = (char[]) privateStringField.get(string4);
		char[] chars5 = (char[]) privateStringField.get(string5); 
		
		System.out.println("++" + chars + "       " + Arrays.toString(chars));
		System.out.println("++" + chars2 + "       " + Arrays.toString(chars2));
		System.out.println("++" + chars3 + "       " + Arrays.toString(chars3));
		System.out.println("++" + chars4 + "        " + Arrays.toString(chars4));
		System.out.println("++" + chars5 + "       " + Arrays.toString(chars5));
		System.out.println("++" + charString + "       " + Arrays.toString(charString));
		System.out.println(string==string2);
		System.out.println(string3==string);
		System.out.println(string4==string);
		System.out.println(string5==string4);
		
		

	}

控制台输出:

++[C@4e25154f       [a, b, c]
++[C@4e25154f       [a, b, c]
++[C@4e25154f       [a, b, c]
++[C@70dea4e        [a, b, c]
++[C@70dea4e        [a, b, c]
++[C@5c647e05      [a, b, e]
true
false
false
false

我们用反射可以拿到char[] 的引用,并打印出char[] 指向的内存地址。
可见前三个String都是指向同一个地址的(字符串常量池),后三个String都是指向堆中的地址。

5思考java中String 不可更改的好处在哪?
1.如果可变复用将变得不稳定。复用可以节约内存
2.hashcode被缓存,没必要重复结算
3.线程安全(网上的说法,我并不完全赞同,能保证值得安全,并不能保证引用的安全总是)
4.如果定义为final 也就是String的引用和内容都会稳定不可变(当然不包括使用反射的情况)

6intern方法的作用?
intern的作用是 将string放入常量池,并返回该引用,如果已经在常量池中直接返回引用。
在JDK1.6之后 intern方法是将不存在字符串常量池的String去记录到常量池里(存的是引用)实例还是在堆上
在JDK1.6之前intern方法是把String复制到字符串常量池里是新对象了(据说是在永久代中)目前可以确定String实例肯定不是一个了,里面的char[]是否复用,这个还不确定,手里没有JDK16的环境,可以用我上面的反射方法来进行验证。

7string的+编译器是如何处理的?
两种情况:
如果只是“” +“”+“”+… 不涉及变量的,javac会直接合并所有的"" “” ,形成utf8 结构体,保存下来,结构体中有个2byte的length字段记录字面量(”“这种东西官方称为字面量)在类运行中会把结构体的东西加载到内存的字符串常量池中(具体加载细节后续再聊)
第二种情况:

        String j1="a";
	    String j2="b";
	    String j12="ab";
	    String j3="a"+j12;
	    System.out.println(j3 == j12); (输出是false)

遇到这种情况javac并不会合并”“ ”“,尽管j12也是字面量的变量。我们可以通过javap -c查看字节码:

Code:
       0: ldc           #2                  // String a
       2: astore_2
       3: ldc           #3                  // String b
       5: astore_3
       6: new           #4                  // class java/lang/StringBuilder
       9: dup
      10: invokespecial #5                  // Method java/lang/StringBuilder."<init>":()V
      13: ldc           #2                  // String a
      15: invokevirtual #6                  // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
      18: aload_3
      19: invokevirtual #6                  // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
      22: invokevirtual #7                  // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
      25: astore        4

很清楚的看到,这里会new StringBuilder 调用append方法,最后toString。StringBulider的toString方法我们可以看一下,是根据当前的char[]去 newString的,所以必然不是用一个对象,所以输出的结果是false。

未完待续…

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

JAVA中String的底层解析 的相关文章

  • 基于Redis的MessageQueue队列封装

    原创文章 xff0c 转载请注明出处 xff1a http www huyanping cn p 61 275 作者 xff1a Jenner Redis的链表List可以用来做链表 xff0c 高并发的特性非常适合做分布式的并行消息传递
  • 基于PHP的crontab定时任务管理

    BY JENNER 2014年11月10日 阅读次数 xff1a 6 linux的crontab一直是服务器运维 业务开展的利器 但当定时任务增多时 xff0c 管理和迁移都变得很麻烦 xff0c 而且容易出问题 下面提供了一个使用php编
  • PHP模拟SQL的GROUP BY算法

    BY JENNER 2015年1月24日 阅读次数 xff1a 25 github地址 xff1a https github com huyanping Zebra PHP ArrayGroupBy packagist地址 xff1a ht
  • flume:支持重命名、移动文件的roll file sink升级版

    原创文章 xff0c 转载请注明 xff1a 转载自始终不够 本文链接地址 flume xff1a 支持重命名 移动文件的roll file sink升级版 转载请注明 xff1a 始终不够 flume xff1a 支持重命名 移动文件的r
  • wordpress全栈优化

    原创文章 xff0c 转载请注明 xff1a 转载自始终不够 本文链接地址 wordpress全栈优化 转载请注明 xff1a 始终不够 wordpress全栈优化 从最开始计算 xff0c 始终不够 个人博客上线已经有两年多了 从最开始就
  • 递归与循环

    原创文章 xff0c 转载请注明 xff1a 转载自始终不够 本文链接地址 递归与循环 转载请注明 xff1a 始终不够 递归与循环 大一学C 43 43 的时候 xff0c 老师说过递归与循环是可以相互转化的 xff0c 当时好像是用来两
  • 安卓仿知乎个人主页,实现嵌套滑动和渐隐效果

    本篇文章已经授权微信公共号guolin blog 郭霖 独家发布 转载请注明作者AndroidMsky和出处 http blog csdn net AndroidMsky article details 53784984 本文github
  • PHP异步编程简述

    概述 异步编程 xff0c 我们从字面上理解 xff0c 可以理解为代码非同步执行的 异步编程可以归结为四种模式 xff1a 回调 事件监听 发布 订阅 promise模式 我们最熟悉的两种模式是回调和事件监听 xff0c 举两个最简单的j
  • CSV是什么文件格式

    CSV 即 Comma Separate Values xff0c 这种文件格式经常用来作为不同程序之间的数据交互的格式 具体文件格式 每条记录占一行 以逗号为分隔符 逗号前后的空格会被忽略 字段中包含有逗号 xff0c 该字段必须用双引号
  • 写给4年前开始编程序的自己

    最近在网上看到有人写了一篇关于 写给4年前没有开始做设计的自己 xff0c 突然也想写这样一篇文章 具体那篇文章的内容我并没有细读 xff0c 防止自己的思路照着他的来 首先 xff0c 我先简单介绍下自己 xff0c 好为后面的内容做一个
  • STM32单片机(七). USART串口、IIC和CAN通信

    在简单的学习过了STM32中的简单外设以及中断系统后 xff0c 在本章节中开始介绍STM32芯片中各个通信接口的配置 在计算机中 xff0c 按数据传输方式可分为串行通信以及并行通信 xff1b 按数据同步方式可分为异步通信和同步通信 x
  • VINS-Mono论文笔记(中)

    VINS Mono论文笔记 中 前言1 初始化过程1 1 视觉重构1 2 视觉惯性联合 2 紧耦合的单目VIO系统2 1 公式2 2 imu残差2 3 视觉残差2 4 边缘化残差2 5 针对相机实时帧率的纯运动视觉惯性状态估计器2 6 im
  • Qt生成exe文件并成功运行

    Qt程序写完后 xff0c 想要生成一个exe文件 xff0c 那么可以参考以下方法 工具 xff1a Qt5 9 9 我们以程序2048为例 将左下角debug改为release xff0c 然后点击左侧 项目 xff0c 找到build
  • 【Qt入门第二篇】基础(二)编写Qt多窗口程序

    导语 程序要实现的功能是 xff1a 程序开始出现一个对话框 xff0c 按下按钮后便能进入主窗口 xff0c 如果直接关闭这个对话框 xff0c 便不能进入主窗口 xff0c 整个程序也将退出 当进入主窗口后 xff0c 我们按下按钮 x
  • Qt之统一的UI界面格式基调,漂亮的UI界面

    今天主要谈谈Qt UI界面统一样式 格式基调 的问题 xff1b 例如在window系统上 xff0c 几乎所有的窗口都有标题栏和状态栏以及中央部件 xff0c 而且每一个标题栏和状态栏以及中央部件样式都保持一致的 xff1b 但是在实际开
  • qt plaintextedit使用_qt获取lineedit的内容

    QLineEdit和QTextEdit都是文本框类 xff0c QLineEdit类是单行文本框控件 xff0c 可以输入单行字符串 QTextEdit类是多行文本框控件 xff0c 可以显示多行文本内容 xff0c 当文本内容超出控件显示
  • Qt实现表格控件

    一 概述 最近在研究QTableView支持多级表头的事情 xff0c 百度了下网上资料还是挺多的 实现的方式总的来说有2种 xff0c 效果都还不错 xff0c 最主要是搞懂其中的原理 xff0c 做到以不变应万变 实现多级表头的方式有以
  • 从h5调起原生APP到自己调起知乎页面

    转载请注明作者AndroidMsky和出处 xff1a http blog csdn net AndroidMsky article details 54316327 效果 xff1a 这篇算兴趣加技术篇 xff0c 和之前的抢红包博文和接
  • Qt经验-按钮长按事件分析

    引言 最近在做qt项目 xff0c 需要对button按钮添加一个长按事件 xff08 比如点击按钮 xff0c 开始运动 松开按钮 xff0c 运动停止 xff09 查了些许资料 xff0c xff08 差点误把QPushButton的p
  • Qt开发-鼠标事件

    引言 个人认为 xff0c 事件机制是Qt最难以理解且最为精妙的一部分 事件主要分为两种 xff1a 在与用户交互时发生 比如按下鼠标 xff08 mousePressEvent xff09 xff0c 敲击键盘 xff08 keyPres

随机推荐

  • Qt Creator工具介绍与使用

    如今 Qt Creator 功能十分强大了 xff0c 包含项目模板生成 代码编辑 UI 设计 QML 界面编辑 调试程序 上下文帮助等丰富功能 xff0c 本文就详细的介绍一下如何使用 Qt 在很长的一段时间内都没有自己的开发环境 xff
  • Qt 封装HTTP网络工具类HttpClient

    一 前言 Qt 使用 QNetworkAccessManager 访问网络 xff0c 这里对其进行了简单的封装 xff0c 访问网络的代码可以简化为 1 GET 请求无参数 HttpClient 34 http localhost 808
  • Qt——线程与定时器

    一 定时器QTimer类 The QTimer class provides repetitive and single shot timers The QTimer class provides a high level programm
  • MQTT连接阿里云IoT

    我们先来看看官方提供的MQTT连接说明 xff0c 如下 xff1a 根据该文档 xff0c 我们大致了解了各个参数的封装方式 xff0c 那么接下来我们就通过QtMqtt的接口来传入这些参数并连接到阿里云IOT 代码片段 来看一些基本的参
  • Qt小程序之QQ登录窗口输入框控件

    代码之路 整体思路即根据focusInEvent和focusOutEvent事件判断焦点是否在输入框中 xff0c 同时重写setPlaceholderText方法 xff0c 把最开始设置的占位字符保存下来 xff0c 然后焦点进入的时候
  • Qt 自定义日志类

    一 前言 C 43 43 中比较不错的日志工具有 log4cxx xff0c log4qt 等 xff0c 但是它们都不能和 qDebug qInfo 等有机的结合在一起 xff0c 所以在 Qt 中使用总觉得不够舒服 xff0c 感谢 Q
  • 在Qt程序中使用C++11线程std::thread处理耗时操作

    Qt界面程序通常什么情况下要使用到线程 xff1f Qt界面程序在调用接口处理时间较长的任务时 如连接网络 复制文件等等耗时操作 xff0c 界面在等待接口返回前会导致卡死 为了不让界面卡死 xff0c 可以使用一个子线程来处理耗时任务 x
  • 学习stm32单片机,必备工具和软件,你知道几个?

    大家好 xff0c 我是华维的麦琪 今天给大家介绍下 xff0c 学习stm32需要用到那些硬件和软件 xff0c 对于学习stm32单片机的学习者 xff0c 要添置必要的学习和开发工具 xff0c 搭建一个最基本的学习平台 xff0c
  • 关于android UI适配的一些思考

    作为前端工程师 xff0c 界面效果 xff0c 效率 肯定是第一要务 面对安卓庞大的机型和屏幕对开发者的要求也就越来越高了 今天笔者就自己对UI适配的一些经验进行一个简短的总结 1 关于xml中写死dp的思考 首先我们应该先把问题抛出 x
  • 单片机编程用什么软件?单片机开发软件有哪些?华维告诉你.

    大家好 xff0c 我是华维 最近有小伙伴问我单片机编程用哪些软件 xff0c 结合我工作10年单片机经验 xff0c 在此回答一下大家的问题 单片机编程软件有很多 xff0c 什么protues仿真 Labview Pycharm等等 x
  • stm32单片机学习秘籍(完整版)

    大家好 xff0c 我是华维麦琪 xff0c 今天来分享下我们华维团队十年经验总结 xff0c 如何能快速学好stm32单片机 xff01 最近看到很多小伙伴学STM32学的一脸懵逼 xff0c 有些甚至学1年都不会 xff0c 有些虽然学
  • 深度解析,单片机运行原理,你知道吗?

    同名回复 入门资料 获取单片机入门到高级进阶教程 单片机是将中央处理单元 xff08 CPU xff09 储存器 输入输出集成在一片芯片上 xff0c 可以说单片机就是一台微型计算机 xff0c 只是和我们平常使用的计算机相比它的功能有所不
  • 玩单片机需要学数电、模电吗?

    首先我们来了解下什么是模电和数电 模拟电路 xff1a 模拟电路是指用来对模拟信号进行传输 变换 处理 放大 测量和显示等工作的电路 模拟信号是指连续变化的电信号 模拟电路是电子电路的基础 xff0c 它主要包括放大电路 信号运算和处理电路
  • 2022年入坑,互联网开发和嵌入式开发,你会选择哪个?

    前言 2022年入坑 xff0c 互联网开发和嵌入式开发 xff0c 你会选择哪个 xff1f 我想很多人会毫不犹豫的选择互联网吧 xff0c 嵌入式没有那么大众化 xff0c 没有那么多关注 xff0c 对它的概念可能没有那么清楚 今天跟
  • 入门必看,51单片机学习三步走

    回想起我初学单片机到现在已经有六年了 学习期间使用了51单片机 XX卡尔单片机 STM16 STM32等单片机 每次接触新的单片机我首先会熟悉它的基本开发 xff0c 然后再通过项目的实现去深入的了解它 大家都知道51单片机是最容易学习的
  • 【华维教学】用STM32Cube和Keil5点亮一个LED

    大家好 xff0c 我是华维 今天我们讲下用STM32CubeMX和Keil5点亮一个LED xff0c 这个项目比较简单 xff0c 大家都可以尝试下 这个就是我们今天的主角 xff0c 这款单片机芯片是STM32F030K6T6 这个开
  • 浅谈ESP8266、ESP32和STM32的区别

    大家好 xff0c 我是华维蔵鹰 xff0c 关注我可以学习更多的单片机知识 今天我们来聊聊ESP8266 ESP32和STM32 乐鑫聚布局联网领域已经有些年头了 xff0c 先是推出了ESP8266这样的低价带有wifi的芯片 xff0
  • 物联网专业未来没有前途了吗?

    大家好 xff0c 我是华维蔵鹰 xff0c 想学习单片机的同学可以关注 私信我 最近在知乎看到一个同学对物联网的前景感觉到迷茫 xff0c 原因是因为某大学的教授去他们那里讲座 xff0c 然后说他们的学校物联网的专业已经没有招新了 xf
  • 面向单片机编程(一)- 单片机该怎么学

    面向单片机编程 xff08 一 xff09 单片机该怎么学 标签 单片机 C51 单片机该怎么学 xff1f 应该从哪里入手 xff1f 要怎么使用单片机实现一个小 xff08 大 xff09 目标 xff1f 下面我也来和大家一起分享一下
  • JAVA中String的底层解析

    JAVA中String 是Final类不能被继承 JAVA 对String的处理和一般Class有所不同 这文章主要是解释一下String的存储模式和java的字符串常量池的机制 xff0c 和几个涉及底层的引用问题解析 首先提出几个问题