最新要闻
- 重点聚焦!大疆Inspire 3无人机来了:配全画幅X9相机、可录8K视频
- 全球速递!用了电信5G 浙大完成中国首例5G超远程机器人肝胆手术:跨越近万里
- 总投资389亿!2023年第一条高铁获批:沿海超级通道定了
- 全球速讯:消息称腾讯XR团队全线解散:成立不到1年!
- 鄱阳湖旗舰店麻辣小龙虾官方大促:1.4 斤29.9元到手
- 深交所向新亚制程发出关注函
- 快看点丨西部数据推出22TB/44TB My Book桌面硬盘 售价高达1500美元
- 曝光交个朋友欠薪 当事人最新回应:罗永浩正积极联系公司解决
- 果粉买不?苹果折叠屏会先拿iPad试水!折叠iPhone风险太高了
- 当前热讯:想要过目不忘?进来学两招、保证不后悔!
- 世界热资讯!12.4万买帕纳梅拉梦碎 首单车主:保时捷傲慢 100万都不卖
- 天天通讯!襄阳市消防救援训练与战勤保障大队成立
- 吴刚谈儿子出演《狂飙》高晓晨:既然选择这条路就要自己走
- 世界即时:尼泊尔载72人客机失事坠毁 初步调查报告:螺旋桨顺桨失去推力
- 环球信息:2023年铁路春运圆满收官:累计发送旅客3.48亿人次 增长37.4%
- 【天天速看料】博主分享特斯拉Model 3P一年使用成本:每公里不到4毛
手机
iphone11大小尺寸是多少?苹果iPhone11和iPhone13的区别是什么?
警方通报辅警执法直播中被撞飞:犯罪嫌疑人已投案
- iphone11大小尺寸是多少?苹果iPhone11和iPhone13的区别是什么?
- 警方通报辅警执法直播中被撞飞:犯罪嫌疑人已投案
- 男子被关545天申国赔:获赔18万多 驳回精神抚慰金
- 3天内26名本土感染者,辽宁确诊人数已超安徽
- 广西柳州一男子因纠纷杀害三人后自首
- 洱海坠机4名机组人员被批准为烈士 数千干部群众悼念
家电
天天头条:String详解
String对象的不可变原因,String对象的内存布局,及String对象之间的执行==
,equals
,+
运算时的分析。
Author: Msuenb
Date: 2023-02-16
(资料图片)
java.lang.String
类代表字符串。String 对象用于保存字符串,也就是一组字符序列。字符串是常量,它们的值在创建后不能更改。
String 的特点
String 是 final 类,不能被其他的类继承
String 类实现了 Comparable 接口,String 对象可以比较大小
String 对象内部是用字符数组保存字符串内容的
JDK9之前是
private final char value[]
数组,JDK9之后是 byte[] 数组"hello"
等效于char[] value = {"h", "e", "l", "l", "o"}
String 对象是不可变对象,一旦进行修改,就会产生新对象
注意:
- String 类的 char[] value 数组是 final 修饰的,说明 value 数组地址不可变,不是数组元素不可变
- 由于 value 数组是 private 的,所以在 String 类外无法直接修改 value 数组的元素值(除非用反射)
- String 类中的方法涉及到 value 数组长度变化,或修改元素值,都是用用新对象来表示修改后内容
final char[] value = {"h", "e", "l", "l", "o"};// value = new char[5]; // value 的地址不可修改value[0] = "H"; // 可以修改 value 元素值String str = "hello";str = "world"; // 不会修改 "hello", 会在池中创建一个新的String对象接受 "world" str指向这个新对象 共会创建两个对象
String 对象不可变,可以共享(节省内存)。Java 中把需要共享的字符串常量对象存放在常量池中。
String s1 = "hello";String s2 = "hello";System.out.println(s1 == s2); // true// 内存中只有一个 "hello" 对象被创建,同时被s1和s2共享
创建String对象
总的来说,String 对象的创建方式有两种:直接赋值 和 使用构造器,这两种方式的机制是不一样的
- 直接赋值:
String str1 = "hello";
- 先从常量池中查看是否有 "hello" 数据空间,如果有,直接指向;如果没有,重新创建,然后指向。
- str1 最终指向的是常量池的空间地址
- 调用构造器:
String str2 = new String("hello")
- 先在堆中创建空间,里面维护了
char[] value
属性。 - 如果常量池中有 "hello" 数据空间,value 直接指向 "hello" 空间;如果没有,重新创建,然后指向。
- str2 最终指向的是堆中的空间地址;value 才是指向常量池的空间地址
- 先在堆中创建空间,里面维护了
String 内存分析
针对下面两行代码分析 String 对象的创建过程和内存布局
String str1 = "hello";String str2 = new String("hello");
String 内存布局:
String 对象创建过程:
String str1 = "hello";
- 先去查看常量池中是否有 "hello" 数据空间,没有,创建 "hello" 数据空间
- 将 "hello" 数据空间的地址返回给 String 对象引用 str
String str2 = new String("hello");
3. 先在堆中开辟空间,里面维护了 value 属性,str2 指向这片空间4. 检查常量池中是否有 "hello" 数据空间,有,value 直接指向 "hello" 数据空间
哪些字符串对象地址放入字符串常量池:
需要共享的字符串地址记录到字符串常量池的table表中,不需要共享的字符串对象其地址值不需要记录到字符串常量池的table表中。除了以下2种,其他的都不放入字符串常量池:1. ""直接的字符串2. 字符串对象.intern()的结果 其他:1. 直接new2. valueOf,copyValueOf等3. 字符串对象拼接:concat拼接 以及 +左右两边出现 非直接""的字符串拼接4. toUpperCase,toLowerCase,substring,repalce等各种String方法得到的字符串其实下面这些方式,本质都是新new的,其地址都是指向堆空间。
String对象的创建形式
String对象的创建方式有两种,使用其它形式生成String对象,像valueOf()
或toString()
,它们在底层也是调用String的构造方法
直接赋值
String str = "hello";
构造方法
用于创建 String 对象的构造方法有很多,比较常用的有以下几个:
public String()
:其表示创建空字符序列。String(String original)
:其表示创建一个与参数相同的字符序列;也即新创建的字符串是该参数字符串的副本。public String(char[] value)
:通过当前参数中的字符数组来构造新的String。public String(byte[] bytes)
:通过使用默认字符集解码当前参数中的字节数组来构造新的String。也可以指定字符集
String str1 = new String(); // 创建一个空字符串String str2 = new String("hello");System.out.println(str1.equals("")); // truechar[] value = {"h", "e", "l", "l", "o"};// 字符数组String str3 = new String(value);byte[] bytes = {104, 101, 108, 108, 111};// 字节数组String str5 = new String(bytes);// hello
valueOf
和copyValueOf
方法:static String copyValueOf(char[] data): 返回指定数组中表示该字符序列的 String
static String valueOf(char[] data) : 返回指定数组中表示该字符序列的 String
static String valueOf(xx value):xx支持各种数据类型,返回各种数据类型的value参数的字符串表示形式。
char[] data = {"h","e","l","l","o","j","a","v","a"};String s1 = String.copyValueOf(data);String s2 = String.copyValueOf(data, 0, 5);// helloString s3 = String.valueOf(237);// 237
连接运算
+
任意数据类型与"字符串"进行拼接,结果都是字符串类型
int num = 123456;String s = num + "";Student stu = new Student();String s2 = stu + "";// 自动调用对象的toString(),然后与 "" 进行拼接
toString
方法Object 类中声明了 toString() 方法,因此任意对象都可以调用 toString 方法,转为字符串类型。
LocalDate today = LocalDate.now();String str = today.toString();System.out.println(str);
String对象比较
== 与 equals
==
:比较的是两个字符串对象的地址boolean equals(Object obj)
方法:比较是两个字符串对象的内容(String 类重写了 equals 方法)
String str1 = "hello";String str2 = "hello";String str3 = new String("hello");String str4 = new String("hello");1System.out.println(str1 == str2); // truestr1 和 str2 都指向池中 "hello" 数据空间System.out.println(str1 == str3); // falsestr3 指向堆中System.out.println(str1.equals(str3)); // truestr1 与 str3 内容都是 "hello"System.out.println(str3 == str4); // falsestr3 与 str3 指向堆中不同的内存空间System.out.println(str3.equals(str4)); // trueSystem.out.println(str1 == str3.intern()); // trueSystem.out.println(str3 == str3.intern()); // false// 常量池中存在 "hello" 数据空间 str2.intern() 返回 "hello" 的引用 与str1相同
intern() 方法说明:执行
str2.intern()
时,会返回常量池中与 str2 内容相同的字符串常量的地址;若池中没有,则将 str2 添加到池中,并返回 str2 的引用
内存布局分析:
str1 和 str2 中的 value 都指向常量池中的 "hello" 数据空间,str1.value == str2.value。
compareTo方法
int compareTo(String str)
方法:String 类型实现了 Comparable 接口, 重写了 compareTo 方法,即 String 对象支持自然排序。
int compareTo(String str) 方法按照字符的 Unicode 编码值进行比较大小的
@Testpublic void test07() { String[] arr = {"java","linux","hadoop","hive","shell","flink","spark"}; Arrays.sort(arr); System.out.println(Arrays.toString(arr));}
+ 与 concat 的区别
拼接两个字符串的方式有两种:连接运算符+
和concat()
方法
String str1 = "hello,";String str2 = "world";String str3 = str1 + str2;String str4 = str1.concat(str2);System.out.println(str3); // helloworldSystem.out.println(str4); // helloworld
str1 + str2
:"..."
常量拼接,编译器直接优化为拼接后的字符串常量值。如,"abc" + "def"
优化等价于"abcdef"
- 非
"..."
常量拼接,编译器优化为 StringBuilder 的 append 方法,然后再把结果 toString。
String str1 = "hello";String str2 = "world";String str3 = "helloworld";String str4 = str1 + str2;// 非 "..." 直接字符串拼接String str5 = str1 + "world";// 非 "..." 直接字符串拼接String str6 = "hello" + "world";// "..." 直接字符串拼接等价于: String str6 = "helloworld";System.out.println(str3 == str4); // falseSystem.out.println(str3 == str5); // falseSystem.out.println(str3 == str6); // true
现在使用
debug
方式追一下String str5 = str1 + "world";
的执行过程,如下:先创建一个 StringBuilder 对象 sb,容量为16,初始为空。
执行
sb.append("hello");
执行
sb.append("world");
调用
sb.toString();
方法,返回 String 对象
最后 str5 会指向堆中的 String 对象,value[] 指向常量池中的 "helloworld" 数据空间。
注意:final String str1 = "hello";// 此时 str1 完全等价于"hello"
final String s1 = "hello";//此时s1完全等价于"hello"final String s2 = "world";//此时s2完全等价于"world"String s3 = "helloworld";String s4 = s1 + s2;String s5 = s1 + "world";String s6 = "hello" + "world";System.out.println(s3 == s4);//trueSystem.out.println(s3 == s5);//trueSystem.out.println(s3 == s6);//true
str1.concat(str2)
:只要拼接的不是空字符串,每次都 new 一个 StringString str1 = "hello";String str2 = "world";String str3 = "helloworld";String str4 = str1.concat(str2);// str2 不是空串 创建一个新对象接受连接后的内容String str5 = str1.concat("world");String str6 = "hello".concat("world");System.out.println(str3 == str4); // falseSystem.out.println(str3 == str5); // falseSystem.out.println(str3 == str6); // false
concat(String)
方法源码:
可变字符序列
因为 String 对象是不可变对象,虽然可以共享常量对象,但是对于频繁字符串的修改和拼接操作,效率极低。因此 Java 提供了可变字符序列 StringBuilder 和 StringBuffer 类型。
StringBuffer
:线程安全的(方法有 synchronized 修饰)StringBuilder
:线程不安全的
StringBuffer和StringBuilder
StringBuffer 与 StringBuilder 最大区别就是在于 StringBuffer 是线程安全的,支持多线程访问;StringBuilder是线程不安全的,在单线程下使用。
StringBuilder 的效率要高于 StringBuffer,通常情况先建议使用 StringBuilder,但在要求线程安全的情况下需要使用String Buffer。
其他方面 StringBuffer 与 StringBuilder 相似:
StringBuffer 和 StringBuilder 都是 final 类,不能被继承
StringBuffer 和 StringBuilder 都继承自 AbstractStringBuilder,有属性
char[] value
,用于存放字符串内容,由于 value 不是 final 类型,因此 value 数组里的内容存放在堆空间,而不是常量池。
StringBuffer 和 StringBuilder 都不用每次都需要创建新对象,所有效高于 String
StringBuffer 和 StringBuilder 有相同扩容机制:初始容量
capacity = 16
,每次扩容为capacity = 2 * capacity + 2
常用的API,StringBuilder、StringBuffer是完全一致的:
StringBuffer append(xx):拼接,追加
StringBuffer insert(int index, xx):在 [index] 位置插入 xx
StringBuffer deleteCharAt(int index):删除[index]位置字符
void setCharAt(int index, xx):替换[index]位置字符
StringBuffer reverse():反转
int indexOf(String str):在当前字符序列中查询str的第一次出现下标
@Testpublic void test1(){ StringBuilder s = new StringBuilder(); s.append("hello").append(true).append("a").append(12).append("world"); System.out.println(s); System.out.println(s.length());}@Testpublic void test2(){ StringBuilder s = new StringBuilder("helloworld"); s.insert(5, "java"); System.out.println(s);}@Testpublic void test3(){ StringBuilder s = new StringBuilder("helloworld"); s.deleteCharAt(4); System.out.println(s);}@Testpublic void test4(){ StringBuilder s = new StringBuilder("helloworld"); s.reverse(); System.out.println(s);}@Testpublic void test5(){ StringBuilder s = new StringBuilder("helloworld"); s.setCharAt(2, "a"); System.out.println(s);}@Testpublic void test6(){ StringBuilder s = new StringBuilder("helloworld"); int index = s.indexOf("owo"); System.out.println(index);}
String,StringBuffer,StringBuilder效率测试
import org.junit.jupiter.api.Test;public class EfficiencyTest { @Test public void test() { long start = System.currentTimeMillis(); stringTest(); // stringBufferTest(); // stringBuilderTest(); long end = System.currentTimeMillis(); long memory = Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory(); System.out.println("String拼接+用时:" + (end - start)); System.out.println("String拼接+占用内存: " + memory); // String StringBuffer StringBuilder // time 5986 5 3 // memory 57263088 43127632 43127912 } public void stringTest() { String str = new String("0"); for (int i = 0; i < 50000; i++) { str += i; } } public void stringBufferTest() { StringBuffer sb = new StringBuffer("0"); for (int i = 0; i < 50000; i++) { sb.append(i); } } public void stringBuilderTest() { StringBuilder sb = new StringBuilder("0"); for (int i = 0; i < 50000; i++) { sb.append(i); } }}
-
计算机导论学习记录(二)
|这个作业属于哪个课程|https: edu cnblogs com campus fzzcxy 2023learning||--|--||这个作业要求在哪里|https: edu cnb
来源: 天天头条:String详解
世界时讯:开心档之Swift 访问控制
计算机导论学习记录(二)
全球微头条丨8个让你收入翻倍的高质量免费网站
重点聚焦!大疆Inspire 3无人机来了:配全画幅X9相机、可录8K视频
全球速递!用了电信5G 浙大完成中国首例5G超远程机器人肝胆手术:跨越近万里
总投资389亿!2023年第一条高铁获批:沿海超级通道定了
全球速讯:消息称腾讯XR团队全线解散:成立不到1年!
鄱阳湖旗舰店麻辣小龙虾官方大促:1.4 斤29.9元到手
深交所向新亚制程发出关注函
全球看点:USRP-2974上安装Ubuntu20.04 + UHD 3.15 + GNU Radio 3.8 过程全记录
VOP 消息仓库演进之路|如何设计一个亿级企业消息平台
【热闻】【管理您的整个软件供应链】上海道宁与Sonatype助力您以更安全的开源更快地交付产品
快看点丨西部数据推出22TB/44TB My Book桌面硬盘 售价高达1500美元
曝光交个朋友欠薪 当事人最新回应:罗永浩正积极联系公司解决
果粉买不?苹果折叠屏会先拿iPad试水!折叠iPhone风险太高了
当前热讯:想要过目不忘?进来学两招、保证不后悔!
世界热资讯!12.4万买帕纳梅拉梦碎 首单车主:保时捷傲慢 100万都不卖
环球视讯!OpenYurt v1.2 亮点速览丨云边流量峰值相比原生 K8s 降低 90%
全球百事通!堆叠柱状图怎么用?速戳!
火山引擎数智平台的这款产品,正在帮助 APP 提升用户活跃度
模型预处理层介绍(3) - IntegerLookup
CC1打不通时的另外一条链CC3
天天通讯!襄阳市消防救援训练与战勤保障大队成立
吴刚谈儿子出演《狂飙》高晓晨:既然选择这条路就要自己走
世界即时:尼泊尔载72人客机失事坠毁 初步调查报告:螺旋桨顺桨失去推力
环球信息:2023年铁路春运圆满收官:累计发送旅客3.48亿人次 增长37.4%
【天天速看料】博主分享特斯拉Model 3P一年使用成本:每公里不到4毛
卖手机壳收入百万:300多元的壳十分畅销
今热点:机器学习-随机森林
【世界独家】docker-compose搭建redis-Cluster集群
环球快资讯丨使用docker部署Python-Flask实现ChatGPT的使用
今日要闻!关于nfs服务启动messages日志中报错-Unable to watch /proc/fs/nfsd/clients: No such file
【世界聚看点】特斯拉不好惹!网红车评人“蔡老板”被判道歉赔10万后:还没饶了他
环球热点评!阿里一面:你做过哪些代码优化?来一个人人可以用的极品案例
天天微头条丨豆瓣仅4分!《三体》动画宣布延播两周:3月4日恢复
全球新消息丨等待16年!好莱坞8.1分末日科幻大片《我是传奇》续集定了:“史皇”出演
【时快讯】罗永浩交个朋友公司被曝欠薪 员工:遭到暴力裁员
天天短讯!二次元真香升级!13代游戏本华硕天选4开启预约
大宇获恐怖电影《咒》IP授权:由《轩辕剑柒》主创张蓁元主导开发
全球观点:02月16日09时广东珠海疫情数据 阳了以后为什么会腰疼?应该怎么办?
树的子结构之先序遍历+二叉树的镜像+对称二叉树
快资讯丨一口气说出 6 种实现延时消息的方案,还有谁不会?!
快看:联发科一夜回到两年前:大家都不换新手机了
弟弟陪姐姐看病:双双确诊甲状腺癌
环球观点:RNG拖欠奖金再上热搜!前俱乐部选手站队喊话还钱
报道:父母高度近视:1岁婴儿近视600度
每日播报!Win10/11后:Linux启动AMD处理器fTPM出现同款间歇性卡顿
tplink路由器怎么重新设置密码?Tplink路由器如何桥接?
mbti哪个脾气最差?哪个mbti最容易抑郁症?
显卡驱动需要更新吗?显卡驱动怎么更新?
项羽墓在哪个地方?项羽墓为什么在山东?
卖惨是什么意思?卖惨的人是什么心理?
保龄球有几个孔?保龄球设备多少钱一套?
长安是唐朝的首都吗?长安是现在的哪个城市?
每日消息!【并查集】连通块中的数量
【热闻】(数据库系统概论|王珊)第三章关系数据库标准语言SQL:习题
Vue 组件之间传递参数
【世界聚看点】关于 layui 弹出一个 DOM 表单的问题
艾斯死的那一集是多少集?艾斯复活是哪一集?
世界最新:马斯克做出重要“交易”:开放北美全部特斯拉超充桩 换取补贴
【全球独家】5月上映!迪士尼《小美人鱼》真人电影新预告发布:特效惊艳
突破事业线
环球观天下!3000元以下唯一的16G内存手机!真我GT Neo5获得天猫京东销量冠军
死磕竞争对手ChatGPT!谷歌要求员工每天花2至4小时测试自家Bard AI
全球球精选!房地产市场支持政策需更精准
安卓导出已安装app的apk
模型预处理层介绍(2) - Hashing
世界信息:男子借朋友12万 1小时后借条变成白纸!网友:防不胜防
顶级富豪果然都惜命 扎克伯格个人安保费一年超1亿元
环球要闻:今起可提前预约个税办税:每天6-22点可在App预约
要闻:接棒年销26万台扫地机器人爆款单品!石头G10S Pure即将正式亮相
天天通讯!吉利中高端新能源系列定名“吉利银河”:每个人都仰望
全球信息:快速搭建一个网关服务,动态路由、鉴权,一网打尽!(含流程图)
全球播报:再有人问你抽象工厂设计模式,把这篇文章丢给他
环球观天下!时间是什么?时间同步是什么?GPS北斗卫星授时又是什么?
世界要闻:《分布式技术原理与算法解析》学习笔记Day13
诺如病毒进入高发期 学校、家庭如何做好预防?一文了解
你怕失业吗?马斯克炮轰人工智能:比核弹头更危险
巴菲特“黄金搭档”芒格盛赞:比亚迪在中国遥遥领先于特斯拉
40岁男子报复10岁小孩连划7车引围观:结局舒适了 网友点赞
《霍格沃茨之遗》更新后PC优化更差!玩家:游戏卡顿问题解决一下
快资讯丨再下一城!百度地图红绿灯倒计时上线兰州:实时读秒
最资讯丨下行5000兆 跟上行同速!谷歌美国推5Gbps光纤:每月850元
全球要闻:读Java实战(第二版)笔记11_语言特性和类库更新
片仔癀珍珠霜的功效
天天热头条丨HEU KMS Activator 28.0.0全能系统数字许可激活工具
CentOS7.9安装K8S高可用集群(三主三从)
Android JetPack~ LiveData (一) 介绍与使用
环球观热点:SDK多项目开发与联调
全球快看:期末复习——线程
环球热点评!5年前就已杀青 周星驰《美人鱼2》进入后期制作
谨慎升级 等了2个月的AMD新驱动疑似翻车:系统崩了
世界热议:央广网:“暴雪式”傲慢引众怒 或终将致其失去中国市场
要闻速递:中国移动:加速千兆网络全面普及 建成全球最大规模光网络
中国快递卷了15年:死死困住了一个50岁的老快递员
纽约黄金期货周三收跌1.1% 创五周来最低收盘价
1998年属虎的人2012年运程
今日聚焦!qq情侣网名 〈談情》**/|(說爰)ⅱ,
80年代的零食大全怀旧辣条_80年代的零食大全怀旧