当前位置: 首页 > 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…...

stm32G473的flash模式是单bank还是双bank?

今天突然有人stm32G473的flash模式是单bank还是双bank&#xff1f;由于时间太久&#xff0c;我真忘记了。搜搜发现&#xff0c;还真有人和我一样。见下面的链接&#xff1a;https://shequ.stmicroelectronics.cn/forum.php?modviewthread&tid644563 根据STM32G4系列参考手…...

376. Wiggle Subsequence

376. Wiggle Subsequence 代码 class Solution { public:int wiggleMaxLength(vector<int>& nums) {int n nums.size();int res 1;int prediff 0;int curdiff 0;for(int i 0;i < n-1;i){curdiff nums[i1] - nums[i];if( (prediff > 0 && curdif…...

【决胜公务员考试】求职OMG——见面课测验1

2025最新版&#xff01;&#xff01;&#xff01;6.8截至答题&#xff0c;大家注意呀&#xff01; 博主码字不易点个关注吧,祝期末顺利~~ 1.单选题(2分) 下列说法错误的是:&#xff08; B &#xff09; A.选调生属于公务员系统 B.公务员属于事业编 C.选调生有基层锻炼的要求 D…...

C# 求圆面积的程序(Program to find area of a circle)

给定半径r&#xff0c;求圆的面积。圆的面积应精确到小数点后5位。 例子&#xff1a; 输入&#xff1a;r 5 输出&#xff1a;78.53982 解释&#xff1a;由于面积 PI * r * r 3.14159265358979323846 * 5 * 5 78.53982&#xff0c;因为我们只保留小数点后 5 位数字。 输…...

Spring是如何解决Bean的循环依赖:三级缓存机制

1、什么是 Bean 的循环依赖 在 Spring框架中,Bean 的循环依赖是指多个 Bean 之间‌互相持有对方引用‌,形成闭环依赖关系的现象。 多个 Bean 的依赖关系构成环形链路,例如: 双向依赖:Bean A 依赖 Bean B,同时 Bean B 也依赖 Bean A(A↔B)。链条循环: Bean A → Bean…...

无人机侦测与反制技术的进展与应用

国家电网无人机侦测与反制技术的进展与应用 引言 随着无人机&#xff08;无人驾驶飞行器&#xff0c;UAV&#xff09;技术的快速发展&#xff0c;其在商业、娱乐和军事领域的广泛应用带来了新的安全挑战。特别是对于关键基础设施如电力系统&#xff0c;无人机的“黑飞”&…...

解读《网络安全法》最新修订,把握网络安全新趋势

《网络安全法》自2017年施行以来&#xff0c;在维护网络空间安全方面发挥了重要作用。但随着网络环境的日益复杂&#xff0c;网络攻击、数据泄露等事件频发&#xff0c;现行法律已难以完全适应新的风险挑战。 2025年3月28日&#xff0c;国家网信办会同相关部门起草了《网络安全…...

解决:Android studio 编译后报错\app\src\main\cpp\CMakeLists.txt‘ to exist

现象&#xff1a; android studio报错&#xff1a; [CXX1409] D:\GitLab\xxxxx\app.cxx\Debug\3f3w4y1i\arm64-v8a\android_gradle_build.json : expected buildFiles file ‘D:\GitLab\xxxxx\app\src\main\cpp\CMakeLists.txt’ to exist 解决&#xff1a; 不要动CMakeLists.…...

PostgreSQL——环境搭建

一、Linux # 安装 PostgreSQL 15 仓库 sudo dnf install -y https://download.postgresql.org/pub/repos/yum/reporpms/EL-$(rpm -E %{rhel})-x86_64/pgdg-redhat-repo-latest.noarch.rpm# 安装之前先确认是否已经存在PostgreSQL rpm -qa | grep postgres# 如果存在&#xff0…...

HybridVLA——让单一LLM同时具备扩散和自回归动作预测能力:训练时既扩散也回归,但推理时则扩散

前言 如上一篇文章《dexcap升级版之DexWild》中的前言部分所说&#xff0c;在叠衣服的过程中&#xff0c;我会带着团队对比各种模型、方法、策略&#xff0c;毕竟针对各个场景始终寻找更优的解决方案&#xff0c;是我个人和我司「七月在线」的职责之一 且个人认为&#xff0c…...