String 进阶
字符串拼接
// 常量与常量的拼接结果放在常量池
// 常量池中不会存在相同的常量
String str1 = "a" + "b";
System.out.println(str1 == "ab");
// 拼接时有一个为变量,则结果会放在堆中。
// 变量拼接的原理是 StringBuilder append 最后toString
// 查看字节码指令就可以看到详细过程
// 就是在堆空间中 new String
String a = "a";
String str2 = a + "b";
System.out.println(str2 == "ab");
// 拼接结果调用 intern 方法,则主动将常量池中还没有的字符串对象放入字符串常量池,并返回对应地址
// 如果常量池中有对应字符串对象,则返回已有的字符串对象地址
String b = "b";
String str3 = ("a" + b).intern();
System.out.println(str3 == "ab");
// final 修饰的变量,在编译时就会进行赋值确定
String str4 = a + b;
System.out.println(str4 == "ab");// false
final String c = "c";
final String d = "d";
String str5 = c + d;
System.out.println(str5 == "cd");// true
使用 StringBulider 进行拼接
int i = 0;
String str = "";
while (i < 1000){str += "a";
}
循环中每次 str + “a” 都会创建一个 StringBuilder ,然后toString。效率极低。
int i = 0;
StringBuilder sb = new StringBuilder();
while (i < 1000){sb.append("a");
}
String str = sb.toString();
只 new 了一个StringBuilder,且只 toString 一次。
进一步优化
int i = 0;
StringBuilder sb = new StringBuilder(1000);
while (i < 1000){sb.append("a");
}
String str = sb.toString();
优化方式和ArrayList一样。如果我们能大概确定要生成的字符串长度,我们可以初始化 StringBuilder 的底层 char[] 数组的长度,避免超过长度时的扩容操作。
new String 会创建几个对象?
String s = new String(“ab”) 会创建两个对象。一个在堆空间,一个在字符串常量池。此时 s 的地址为指向堆空间的字符串对象。
具体可以在 idea 中下载 jclasslib 插件,查看字节码的方式来解释
引申
new String("a") + new String("b") // 创建了几个对象?
1. new String("a") 创建两个对象,堆和常量池
2. new String("b") 创建两个对象,堆和常量池
3. 两个非常量相加,会创建一个 StringBuilder 对象使用其 append 方法,最后 toString
4. toString 方法会 new 一个 String 对象(但其不会在常量池生成对象"ab")
intern 方法的使用
public native String intern();
intern 是一个 native 方法,如果当前常量池没有当前字符串对应相等(equals 为 true)的字符串,则将对象放入字符串常量池,并返回对应地址。如果常量池中有对应字符串对象,则返回已有的字符串对象地址
示例
String a = new String("a");
a.intern();
System.out.println(a == "a"); //jdk6 false jdk1.7+ falseString b = new String("b") + new String("b");
b.intern();
System.out.println(b == "bb");//jdk6 false jdk1.7+ true
对象 a 指向的时堆中的字符串对象地址,“a” 放在常量池的,所以为 false
new String(“b”) + new String(“b”) 不会在常量池创建对象 “ab”,其主要问题是,jdk1.7+ 环境中,在调用 intern 方法的时候,不是在常量池中创建一个新的对象 “ab”,而是将当前堆中 new 的 “ab” 的引用赋值给了常量池的引用,导致堆和常量池中的引用都指向了同一个地址。基于此特性,下面的示例结果就能够解释了。
String c = new String("c") + new String("c");
String cc = "cc";
c.intern(); // 当前 "cc" 在常量池已经存在,且和堆中的对象引用不同
System.out.println(c == cc);// jdk1.7+ falseString d = new String("d") + new String("d");
d.intern();// 此时 "dd" 在常量池还不存在,基于上面的解释,此时堆和常量池中的"dd"对象的引用是一致的
String dd = "dd";
System.out.println(d == dd);// jdk1.7+ true
intern 使用技巧
大量的 String 对象使用的时候,比如:String 数组或大的集合中存放 String 对象,可以对String对象先调用 intern 方法返回常量池引用后存放。这样的好处是,最后这些大量的引用都引用的常量池的对象,堆中的对象可以正常 GC 释放。此方式特别在有大量重复字符串对象的时候能节省大量的空间。
相关文章:

String 进阶
字符串拼接 // 常量与常量的拼接结果放在常量池 // 常量池中不会存在相同的常量 String str1 "a" "b"; System.out.println(str1 "ab");// 拼接时有一个为变量,则结果会放在堆中。 // 变量拼接的原理是 StringBuilder append 最后…...
ESP32设备通信-两个ESP32间UART通信
两个ESP32间UART通信 文章目录 两个ESP32间UART通信1、UART介绍2、软件准备3、硬件准备4、代码实现在本文中,我们将使用 Arduino IDE 的 UART 硬件库在两个 ESP32 板之间执行 UART 或串行通信。 要使用 USB 端口调试和编程 ESP32,需要使用称为通用异步接收器/发送器 (UART) 通…...
LCR 052.递增顺序搜索树
题目来源: leetcode题目,网址:LCR 052. 递增顺序搜索树 - 力扣(LeetCode) 解题思路: 中序遍历时修改指针即可。 解题代码: /*** Definition for a binary tree node.* public class TreeNo…...
Mysql集群技术问答
前提:Mysql集群服务部署到一个群组的所有服务器上,一般20台为一个群组,群组内所有节点数据实时同步,动态自动维护节点。 问:集群空间跟传统空间的最大不同是什么? 答:集群空间有数据同步和宕机检…...

2023版 STM32实战4 滴答定时器精准延时
SysTick简介与特性 -1- SysTick属于系统时钟。 -2- SysTick定时器被捆绑在NVIC中。 -3- SysTick可以产生中断,且中断不可屏蔽。 SysTick的时钟源查看 通过时钟树可以看出滴答的时钟最大为72MHZ/89MHZ 通过中文参考手册也可以得到这个结论 代码编写(已经验证&a…...
ESP32设备驱动-数据持久化到Flash
数据持久化到Flash 文章目录 数据持久化到Flash1、Preferences库介绍2、软件准备3、硬件准备4、代码实现4.1 初始化NVS Flash4.2 读写Key/Value对4.3 保存/读取网络凭据4.4 复位后记住最后的 GPIO 状态在本文中,我们将介绍如何使用 Preferences库将数据存储到 ESP32 的Flash中…...

Swift data范围截取问题
文章目录 一、截取字符串的几种方法1. 截取前几位2. 截取后几位3. subData4. 下标截取 二、subData(in:) 报错 EXC_BREAKPOINT 一、截取字符串的几种方法 1. 截取前几位 mobileID.prefix(32)2. 截取后几位 mobileID.suffix(3)3. subData data.subdata(in: 0..<4)4. 下标…...

PICO首届XR开发者挑战赛正式启动,助推行业迈入“VR+MR”新阶段
9月25日,“PICO 2023首届XR开发者挑战赛”(下文简称“挑战赛”)媒体启动会在北京圆满落幕,官方赛事报名通道已于今日开启。据悉,本次挑战赛是PICO首次针对全球开发者举办的大型挑战赛事,旨在与开发者保持连…...

【计算机网络】应用层协议原理
文章目录 网络应用程序体系结构客户-服务器体系结构P2P体系结构 进程通信客户和服务器进程进程与计算机网络之间的接口进程寻址 可供应用程序使用的运输服务可靠数据传输吞吐量定时安全性 因特网提供的运输服务TCP服务面向连接的服务可靠数据传输服务TCP安全 UDP服务因特网运输…...

buuctf-[WUSTCTF2020]CV Maker
打开环境 随便登录注册一下 进入到了profile.php 其他没有什么页面,只能更换头像上传文件,所以猜测是文件上传漏洞 上传一句话木马看看 <?php eval($_POST[a]);?>回显 搜索一下 添加文件头GIF89a。上传php文件 查看页面源代码,看…...
数据库表操作详解
在数据库管理中,表操作是最基础也最常用的一项功能。不论是临时存储一些数据,还是通过派生表进行复杂的查询,表操作的灵活性和多样性都使其在数据库中发挥着重要的作用。 本文将详细解析数据库中常见的表操作,包括临时表、派生表以及与视图、子查询的比较。我们将使用游戏…...
axios配置代理ip
axios配置代理ip 对于在nodejs中使用axios作为请求库时,有需要配置代理ip的需求(比如爬虫等等) 最离谱的是,在网上搜了一圈,全是关于axios配置proxy跨域的解决办法,没有配置代理ip的方法。 const axios …...

Apache Commons Pool2 池化技术
对象池是一种设计模式,用于管理和重用对象,以提高性能和资源利用率。对象池的概念在许多应用程序中都有广泛应用,特别是在需要频繁创建和销毁对象的情况下,例如数据库连接、线程、HTTP连接等 对象池通过预先创建一组对象并将它们存…...

二叉树的最近公共祖先LCA
系列题目 236. 二叉树的最近公共祖先 1676. 二叉树的最近公共祖先IV 1644. 二叉树的最近公共祖先 II 235. 二叉搜索树的最近公共祖先 1650. 二叉树的最近公共祖先 III class LowestCommonAncestor:"""236. 二叉树的最近公共祖先题目强调p和q一定存在于二叉树中&…...

AWS SAA知识点整理(作成中)
共通 一些信息已经更新了,但参考题的答案还是旧的。 比如: S3的最大读写性能已经提高到 3,500 PUT/COPY/POST/DELETE or 5,500 GET/HEAD requests per second 并且不再要求使用random prefix 题目中有时候会让选择Not violation 不合适的一项ÿ…...
C++模板大全(持续更新,依不同网站整理而成)
C模板大全 基本模板快读快写快读快写火车头缺省源 基本算法暴力枚举模拟贪心二分三分尺取法分治前缀和差分递推递归倍增排序sort冒泡排序桶排序选择排序插入排序希尔排序归并排序快速排序堆排序计数排序基数排序 基础数据结构栈队列哈希链表单向链表双向链表 单调栈单调队列 高…...

《CTFshow-Web入门》10. Web 91~110
Web 入门 索引web91题解总结 web92题解总结 web93题解 web94题解 web95题解 web96题解 web97题解 web98题解 web99题解总结 web100题解 web101题解 web102题解 web103题解 web104题解 web105题解总结 web106题解 web107题解 web108题解 web109题解 web110题解 ctf - web入门 索…...

计组--总线
一、概念 总线是一组能为多个部件分时共享的公共信息传送线路。 共享是指总线上可以挂接多个部件,各个部件之间互相交换的信息都可以通过这组线路分时共享。 分时是指同一时刻只允许有一个部件向总线发送信息,如果系统中有多个部件,则它们…...
Git中的HEAD
Git中的HEAD HEAD^数字:表示当前提交的父提交,具体是第几个父提交通过数字指定,HEAD^1第一个父提交,该语法只 能用于合并(merge)的提交记录,因为一个通过合并产生的commit对象才有多个父提交。 HEAD~数字࿱…...

软件设计师_数据库系统_学习笔记
文章目录 3.1 数据库模式3.1.1 三级模式 两级映射3.1.2 数据库设计过程 3.2 ER模型3.3 关系代数与元组演算3.4 规范化理论3.5 并发控制3.6 数据库完整性约束3.7 分布式数据库3.8 数据仓库与数据挖掘 3.1 数据库模式 3.1.1 三级模式 两级映射 内模式直接与物理数据库相关联的 定…...

【WiFi帧结构】
文章目录 帧结构MAC头部管理帧 帧结构 Wi-Fi的帧分为三部分组成:MAC头部frame bodyFCS,其中MAC是固定格式的,frame body是可变长度。 MAC头部有frame control,duration,address1,address2,addre…...

Vue2 第一节_Vue2上手_插值表达式{{}}_访问数据和修改数据_Vue开发者工具
文章目录 1.Vue2上手-如何创建一个Vue实例,进行初始化渲染2. 插值表达式{{}}3. 访问数据和修改数据4. vue响应式5. Vue开发者工具--方便调试 1.Vue2上手-如何创建一个Vue实例,进行初始化渲染 准备容器引包创建Vue实例 new Vue()指定配置项 ->渲染数据 准备一个容器,例如: …...

Cinnamon修改面板小工具图标
Cinnamon开始菜单-CSDN博客 设置模块都是做好的,比GNOME简单得多! 在 applet.js 里增加 const Settings imports.ui.settings;this.settings new Settings.AppletSettings(this, HTYMenusonichy, instance_id); this.settings.bind(menu-icon, menu…...
LangChain知识库管理后端接口:数据库操作详解—— 构建本地知识库系统的基础《二》
这段 Python 代码是一个完整的 知识库数据库操作模块,用于对本地知识库系统中的知识库进行增删改查(CRUD)操作。它基于 SQLAlchemy ORM 框架 和一个自定义的装饰器 with_session 实现数据库会话管理。 📘 一、整体功能概述 该模块…...

[大语言模型]在个人电脑上部署ollama 并进行管理,最后配置AI程序开发助手.
ollama官网: 下载 https://ollama.com/ 安装 查看可以使用的模型 https://ollama.com/search 例如 https://ollama.com/library/deepseek-r1/tags # deepseek-r1:7bollama pull deepseek-r1:7b改token数量为409622 16384 ollama命令说明 ollama serve #:…...

Rust 开发环境搭建
环境搭建 1、开发工具RustRover 或者vs code 2、Cygwin64 安装 https://cygwin.com/install.html 在工具终端执行: rustup toolchain install stable-x86_64-pc-windows-gnu rustup default stable-x86_64-pc-windows-gnu 2、Hello World fn main() { println…...

AD学习(3)
1 PCB封装元素组成及简单的PCB封装创建 封装的组成部分: (1)PCB焊盘:表层的铜 ,top层的铜 (2)管脚序号:用来关联原理图中的管脚的序号,原理图的序号需要和PCB封装一一…...
React核心概念:State是什么?如何用useState管理组件自己的数据?
系列回顾: 在上一篇《React入门第一步》中,我们已经成功创建并运行了第一个React项目。我们学会了用Vite初始化项目,并修改了App.jsx组件,让页面显示出我们想要的文字。但是,那个页面是“死”的,它只是静态…...

麒麟系统使用-进行.NET开发
文章目录 前言一、搭建dotnet环境1.获取相关资源2.配置dotnet 二、使用dotnet三、其他说明总结 前言 麒麟系统的内核是基于linux的,如果需要进行.NET开发,则需要安装特定的应用。由于NET Framework 是仅适用于 Windows 版本的 .NET,所以要进…...
js 设置3秒后执行
如何在JavaScript中延迟3秒执行操作 在JavaScript中,要设置一个操作在指定延迟后(例如3秒)执行,可以使用 setTimeout 函数。setTimeout 是JavaScript的核心计时器方法,它接受两个参数: 要执行的函数&…...