当前位置: 首页 > news >正文

聊聊Java中的常用类String

String、StringBuffer、StringBuilder 的区别

从可变性分析

  1. String不可变。
  2. StringBufferStringBuilder都继承自AbstractStringBuilder ,两者的底层的数组value并没有使用privatefinal修饰,所以是可变的。

AbstractStringBuilder 源码如下所示

abstract class AbstractStringBuilder implements Appendable, CharSequence {char[] value;public AbstractStringBuilder append(String str) {if (str == null)return appendNull();int len = str.length();//确定数组空间是否充足,若不充足则动态扩容ensureCapacityInternal(count + len);//这里会进行数组拷贝将新字符串存到数组中str.getChars(0, len, value, count);count += len;return this;}}

从线程安全性考虑

  1. String类是常量线程安全。
  2. StringBuilder 线程不安全。
  3. StringBuffer线程安全。

从性能上分析

  1. String是常量每次添加字符串都会将引用指向新的字符串。
  2. StringBuilder 非线程安全所以性能上相较于StringBuffer会快10%-15%

三者使用场景建议

  1. 操作少量数据,String即可
  2. 单线程操作大量字符串,建议使用StringBuilder
  3. 多线程用StringBuffer

为什么String 是不可变的?

从源码可以看到String底层是使用字符数组存储值的,之所以不可变是因为:

  1. value私有且final也没有对外提供字符串操作的方法。
  2. 类设置为final,子类也无法继承该类对其进行修改。
public final class Stringimplements java.io.Serializable, Comparable<String>, CharSequence {/** The value is used for character storage. */private final char value[];
}

字符串拼接用“+” 的底层工作机制是什么?

如下所示代码

public class StringTest {@Testpublic void addTest() {String s1 = "hello";String s2 = "world";String s3 = "guy";String s4 = s1 + s2 + s3;}
}

查看其字节码可以看到JVM为了避免大量常量创建,会将其进行优化,改用StringBuilder进行拼接后toString

INVOKESPECIAL java/lang/StringBuilder.<init> ()VALOAD 1INVOKEVIRTUAL java/lang/StringBuilder.append (Ljava/lang/String;)Ljava/lang/StringBuilder;ALOAD 2INVOKEVIRTUAL java/lang/StringBuilder.append (Ljava/lang/String;)Ljava/lang/StringBuilder;ALOAD 3INVOKEVIRTUAL java/lang/StringBuilder.append (Ljava/lang/String;)Ljava/lang/StringBuilder;INVOKEVIRTUAL java/lang/StringBuilder.toString ()Ljava/lang/String;ASTORE 4

但是在循环体内使用+=的情况下很可能造成性能灾难。

@Testpublic void addTest2() {String[] arr = {"hello", "world", "guys"};String string = "";for (int i = 0; i < arr.length; i++) {string += arr[i];}}

可以看到在循环体内会不断创建StringBuilder进行拼接。

在这里插入图片描述

来看看我们手动创建StringBuilder 进行拼接和+=JVM优化后的性能差距

@Testpublic void addTest2() {String[] arr = new String[1000];for (int i = 0; i < arr.length; i++) {arr[i] = String.valueOf(i);}long start = System.currentTimeMillis();String string = "";for (int i = 0; i < arr.length; i++) {string += arr[i];}long end = System.currentTimeMillis();System.out.println("使用+=耗时:" + (end - start));start = System.currentTimeMillis();StringBuilder builder =new StringBuilder();for (int i = 0; i < arr.length; i++) {builder.append(arr[i]);}end = System.currentTimeMillis();System.out.println("使用StringBuilder耗时:" + (end - start));}

输出结果,可以看到StringBuilder+=快了将近6倍。

使用+=耗时:6
使用StringBuilder耗时:1

String和Object的equals() 有什么区别

Stringequals进行了重写,String比较的是字符串的值是否一致

public boolean equals(Object anObject) {if (this == anObject) {return true;}if (anObject instanceof String) {String anotherString = (String)anObject;int n = value.length;if (n == anotherString.value.length) {char v1[] = value;char v2[] = anotherString.value;int i = 0;while (n-- != 0) {if (v1[i] != v2[i])return false;i++;}return true;}}return false;}

Object比较的则是两者的引用地址是否一致

public boolean equals(Object obj) {return (this == obj);}

字符串常量池是什么,它有什么用?

如下代码所示,Java会将字符串存放在方法区的字符串常量池,后续如有变量需要可以直接复用,关于字符串常量池后文会介绍。

@Testpublic void stringConst(){String s1="s";String s2="s";System.out.println(s1==s2);//true}

图解String s1 = new String(“abc”);

这段代码实际上会创建两个对象:

  1. 创建String对象s1指向堆区的String对象
  2. 在字符串常量池中创建字符串abc

在这里插入图片描述

intern 方法是什么?有什么用?

该方法会将字符串值存放到字符串常量池中,并返回该引用。注意如果常量池存在则直接返回引用。若不存在才会创建并返回引用。

常量intern

可以看到下面这段代码,调用intern 的字符串和常量池的对象==比较返回的是true

 @Testpublic void internTest() {String s1 = "s";String s2 = s1.intern();String s3 = new String("s");String s4 = s3.intern();System.out.println(s1 == s2);//trueSystem.out.println(s3 == s4);//falseSystem.out.println(s1 == s4);//true}

常量+=intern

再补充一个神奇的现象,常量字符串进行+=时会被JVM在编译自动优化,例如String s1="a"+"b"实际上会被优化为String s1="ab",所以下面这段intern就会出现下面的结果:

原因也很简单:

对于编译期可以确定值的字符串,也就是常量字符串 ,JVM 会将其存入字符串常量池。并且,字符串常量拼接得到的字符串常量在编译阶段就已经被存放字符串常量池,这个得益于编译器的优化。 在编译过程中,Javac 编译器会进行一个叫做 常量折叠(Constant Folding) 的代码优化。
这里说到一个叫常量折叠的概念,常量折叠就是将常量表达式计算求值,并用求得的值来替换表达式,然后放到常量表中的一种机制。

@Testpublic void internTest2() {String s1 = "s"+"tring";String s2 = "string";String s3 = new String("string");String s4 = s3.intern();System.out.println(s1 == s2);//trueSystem.out.println(s3 == s4);//falseSystem.out.println(s1 == s4);//true}

这一点我们查看字节码文件就得以印证

在这里插入图片描述

final+=的intern

final字符串会被JVM优化为常量,所以下面这段代码也会返回true

@Testpublic void internTest3() {final String s1 = "hello";final String s2 = "world";String s3 = s1 + s2;String s4 = "helloworld";System.out.println(s3 == s4);//true}

查看字节码得以印证。

在这里插入图片描述

引用或者函数获取的+=

注意JVM不会对引用和方法这种动态变化的情况进行优化,所以下面这段代码就会返回false

@Testpublic void internTest3() {final String s1 = "hello";final String s2 = getStr();String s3 = s1 + s2;String s4 = "helloworld";System.out.println(s3 == s4);//false}private String getStr() {return "world";}

参考文献

Java基础常见面试题总结(中)

相关文章:

聊聊Java中的常用类String

String、StringBuffer、StringBuilder 的区别 从可变性分析 String不可变。StringBuffer、StringBuilder都继承自AbstractStringBuilder &#xff0c;两者的底层的数组value并没有使用private和final修饰&#xff0c;所以是可变的。 AbstractStringBuilder 源码如下所示 ab…...

R语言piecewiseSEM结构方程模型在生态环境领域实践技术

结构方程模型&#xff08;Sructural Equation Modeling&#xff0c;SEM&#xff09;可分析系统内变量间的相互关系&#xff0c;并通过图形化方式清晰展示系统中多变量因果关系网&#xff0c;具有强大的数据分析功能和广泛的适用性&#xff0c;是近年来生态、进化、环境、地学、…...

IDEA设置查看JDK源码

问题 我们在查看JDK源码时&#xff0c;可能会遇到这种情况&#xff0c;步入底层查看JDK源码时&#xff0c;出现一堆var变量&#xff0c;可读性非常之差&#xff0c;例如笔者最近想看到nio包下的SocketChannelImpl的write方法&#xff0c;结果看到这样一番景象&#xff1a; pu…...

SSM—Mybatis

目录 和其它持久化层技术对比 搭建MyBatis 开发环境 创建maven工程 创建MyBatis的核心配置文件 创建mapper接口 创建MyBatis的映射文件 通过junit测试功能 加入log4j日志功能 核心配置文件详解 MyBatis的增删改查 新增 删除 修改 查询一个实体类对象 查询list集…...

MYSQL在不删除数据的情况下,重置主键自增id

MYSQL在不删除数据的情况下&#xff0c;重置主键自增id 方法一&#xff1a; SET num : 0; UPDATE table_name SET id num : (num1); ALTER TABLE table_name AUTO_INCREMENT 1; 方法二&#xff1a; 背景(mysql 数据在进行多次删除新增之后id变得很大&#xff0c;但是并没…...

SpringMVC-servlet交互

servlet交互 1.1 引入servlet依赖 <dependency><groupId>javax.servlet</groupId><artifactId>javax.servlet-api</artifactId><version>4.0.1</version><scope>provided</scope></dependency>1.2 创建testservl…...

DICOM 文件中,VR,VL,SQ,图像二进制的几个注意点

DICOM 文件的结构&#xff0c;在网上有很多的学习资料&#xff0c;这里只介绍些容易混淆的概念&#xff0c;作为回看笔记。 1. 传输语法 每个传输语法&#xff0c;起都是表达的三个概念&#xff1a;大小端、显隐式、压缩算法 DICOM Implicit VR Little Endian: 1.2.840.1000…...

git 的使用

git reset详解-CSDN博客 git reset 命令详解 git revert命令详解。-CSDN博客 关于Git分支中HEAD和Master的理解 - 知乎 (zhihu.com) 一文带你精通 Git&#xff08;Git 安装与使用、Git 命令精讲、项目的推送与克隆&#xff09;-CSDN博客 Git 常用操作&#xff08;5&#xff…...

详解—【C++】lambda表达式

目录 前言 一、lambda表达式 二、lambda表达式语法 2.1. lambda表达式各部分说明 2.2. 捕获列表说明 三、函数对象与lambda表达式 前言 在C98中&#xff0c;如果想要对一个数据集合中的元素进行排序&#xff0c;可以使用std::sort方法。 #include <algorithm> #i…...

Qt Desktop Widgets 控件绘图原理逐步分析拆解

Qt 是目前C语言首选的框架库。之所以称为框架库而不单单是GUI库&#xff0c;是因为Qt提供了远远超过GUI的功能封装&#xff0c;即使不使用GUI的后台服务&#xff0c;也可以用Qt大大提高跨平台的能力。 仅就界面来说&#xff0c;Qt 保持各个平台绘图等效果的统一&#xff0c;并…...

什么是rocketmq❓

在大规模分布式系统中&#xff0c;各个服务之间的通信是至关重要的&#xff0c;而RocketMQ作为一款分布式消息中间件&#xff0c;为解决这一问题提供了强大的解决方案。本文将深入探讨RocketMQ的基本概念、用途&#xff0c;以及在实际分布式系统中的作用&#xff0c;并对Produc…...

【网络安全】HTTP Slowloris攻击原理解析

文章目录 Slowloris攻击的概念Slowloris攻击原理Slowloris攻击的步骤其他的DDoS攻击类型UDP FloodICMP (Ping) FloodSYN FloodPing of DeathNTP AmplificationHTTP FloodZero-day DDoS 攻击 推荐阅读 Slowloris攻击的概念 Slowloris是在2009年由著名Web安全专家RSnake提出的一…...

从最近爆火的ChatGPT,我看到了电商的下一个形态

爆火的ChatGPT似乎让每个行业有了改造的可能性&#xff0c;电商行业也不例外。 在讨论了很多流量红利消失的话题后&#xff0c;我们看到互联网电商行业不再性感&#xff0c;从淘宝天猫&#xff0c;京东&#xff0c;到拼多多&#xff0c;再到抖音&#xff0c;快手&#xff0c;电…...

云原生向量计算引擎 PieCloudVector:为大模型提供独特记忆

拓数派大模型数据计算系统&#xff08;PieDataComputingSystem&#xff0c;缩写&#xff1a;πDataCS&#xff09;在10月24日程序员节「大模型数据计算系统」2023拓数派年度技术论坛正式发布。πDataCS 以云原生技术重构数据存储和计算&#xff0c;「一份存储&#xff0c;多引擎…...

大创项目推荐 深度学习 opencv python 实现中国交通标志识别

文章目录 0 前言1 yolov5实现中国交通标志检测2.算法原理2.1 算法简介2.2网络架构2.3 关键代码 3 数据集处理3.1 VOC格式介绍3.2 将中国交通标志检测数据集CCTSDB数据转换成VOC数据格式3.3 手动标注数据集 4 模型训练5 实现效果5.1 视频效果 6 最后 0 前言 &#x1f525; 优质…...

深度学习实战67-基于Stable-diffusion的图像生成应用模型的搭建,在Kaggle平台的搭建部署,解决本地没有算力资源问题

大家好,我是微学AI,今天给大家介绍一下深度学习实战67-基于Stable-diffusion的图像生成应用模型的搭建,在Kaggle平台的搭建部署,解决本地没有算力资源问题。稳定扩散模型(Stable Diffusion Model)是一种用于图像增强和去噪的计算机视觉算法。它通过对输入图像进行扩散过程…...

云原生之深入解析Kubernetes本地持久化存储方案OpenEBS LocalPV的最佳实践

一、K8s 本地存储 K8s 支持多达 20 种类型的持久化存储&#xff0c;如常见的 CephFS 、Glusterfs 等&#xff0c;不过这些大都是分布式存储&#xff0c;随着社区的发展&#xff0c;越来越多的用户期望将 K8s 集群中工作节点上挂载的数据盘利用起来&#xff0c;于是就有了 loca…...

设计模式-策略(Strategy)模式

又被称为政策&#xff08;方针&#xff09;模式策略模式(Strategy Design Pattern)&#xff1a;封装可以互换的行为&#xff0c;并使用委托来决定要使用哪一个策略模式是一种行为设计模式&#xff0c;它能让你定义一系列算法&#xff0c;并将每种算法分别放入独立的类中&#x…...

Star 4.1k!Gitee GVP开源项目!新一代桌面应用开发框架 ElectronEgg!

前言 随着现代技术的快速升级迭代及发展&#xff0c;桌面应用开发已经变得越来越普及。然而对于非专业桌面应用开发工程师在面对这项任务时&#xff0c;可能会感到无从下手&#xff0c;甚至觉得这是一项困难的挑战。 本篇文章将分享一种新型桌面应用开发框架 ElectronEgg&…...

node.js学习(简单聊天室)

在掘金查看该文章 1. TCP服务搭建 1.1 socket 先来粗略了解下socket 套接字&#xff08;socket&#xff09;是一个抽象层&#xff0c;应用程序可以通过它发送或接收数据&#xff0c;可对其进行像对文件一样的打开、读写和关闭等操作。套接字允许应用程序将I/O插入到网络中&am…...

HTML 列表、表格、表单

1 列表标签 作用&#xff1a;布局内容排列整齐的区域 列表分类&#xff1a;无序列表、有序列表、定义列表。 例如&#xff1a; 1.1 无序列表 标签&#xff1a;ul 嵌套 li&#xff0c;ul是无序列表&#xff0c;li是列表条目。 注意事项&#xff1a; ul 标签里面只能包裹 li…...

React19源码系列之 事件插件系统

事件类别 事件类型 定义 文档 Event Event 接口表示在 EventTarget 上出现的事件。 Event - Web API | MDN UIEvent UIEvent 接口表示简单的用户界面事件。 UIEvent - Web API | MDN KeyboardEvent KeyboardEvent 对象描述了用户与键盘的交互。 KeyboardEvent - Web…...

Python如何给视频添加音频和字幕

在Python中&#xff0c;给视频添加音频和字幕可以使用电影文件处理库MoviePy和字幕处理库Subtitles。下面将详细介绍如何使用这些库来实现视频的音频和字幕添加&#xff0c;包括必要的代码示例和详细解释。 环境准备 在开始之前&#xff0c;需要安装以下Python库&#xff1a;…...

CMake控制VS2022项目文件分组

我们可以通过 CMake 控制源文件的组织结构,使它们在 VS 解决方案资源管理器中以“组”(Filter)的形式进行分类展示。 🎯 目标 通过 CMake 脚本将 .cpp、.h 等源文件分组显示在 Visual Studio 2022 的解决方案资源管理器中。 ✅ 支持的方法汇总(共4种) 方法描述是否推荐…...

LeetCode - 199. 二叉树的右视图

题目 199. 二叉树的右视图 - 力扣&#xff08;LeetCode&#xff09; 思路 右视图是指从树的右侧看&#xff0c;对于每一层&#xff0c;只能看到该层最右边的节点。实现思路是&#xff1a; 使用深度优先搜索(DFS)按照"根-右-左"的顺序遍历树记录每个节点的深度对于…...

深度学习水论文:mamba+图像增强

&#x1f9c0;当前视觉领域对高效长序列建模需求激增&#xff0c;对Mamba图像增强这方向的研究自然也逐渐火热。原因在于其高效长程建模&#xff0c;以及动态计算优势&#xff0c;在图像质量提升和细节恢复方面有难以替代的作用。 &#x1f9c0;因此短时间内&#xff0c;就有不…...

基于IDIG-GAN的小样本电机轴承故障诊断

目录 🔍 核心问题 一、IDIG-GAN模型原理 1. 整体架构 2. 核心创新点 (1) ​梯度归一化(Gradient Normalization)​​ (2) ​判别器梯度间隙正则化(Discriminator Gradient Gap Regularization)​​ (3) ​自注意力机制(Self-Attention)​​ 3. 完整损失函数 二…...

面试高频问题

文章目录 &#x1f680; 消息队列核心技术揭秘&#xff1a;从入门到秒杀面试官1️⃣ Kafka为何能"吞云吐雾"&#xff1f;性能背后的秘密1.1 顺序写入与零拷贝&#xff1a;性能的双引擎1.2 分区并行&#xff1a;数据的"八车道高速公路"1.3 页缓存与批量处理…...

动态规划-1035.不相交的线-力扣(LeetCode)

一、题目解析 光看题目要求和例图&#xff0c;感觉这题好麻烦&#xff0c;直线不能相交啊&#xff0c;每个数字只属于一条连线啊等等&#xff0c;但我们结合题目所给的信息和例图的内容&#xff0c;这不就是最长公共子序列吗&#xff1f;&#xff0c;我们把最长公共子序列连线起…...

Qt Quick Controls模块功能及架构

Qt Quick Controls是Qt Quick的一个附加模块&#xff0c;提供了一套用于构建完整用户界面的UI控件。在Qt 6.0中&#xff0c;这个模块经历了重大重构和改进。 一、主要功能和特点 1. 架构重构 完全重写了底层架构&#xff0c;与Qt Quick更紧密集成 移除了对Qt Widgets的依赖&…...