深入String、StringBuffer、String 实例化有两种方式、String、StringBuffer常用方法

news/2025/3/11 15:34:19/文章来源:https://www.cnblogs.com/shuwu888/p/18765165

DAY9.1 Java核心基础

String

String 开发使用的频率高

String 实例化有两种方式

1、直接赋值

String str1 ="Word";

2、通过构造函数创建对象

String str2 =new String("Word");

字符串对象底层的基本数据类型是char

比如Word,是char[] str ={'W','o','r','d'};

两种实例化的区别

先看一个代码示例:

public static void main(String[] args) {String str1 ="Word";String str2 ="Word";String str3 =new String("Word");String str4 =new String("Word");System.out.println(str1 == str2);System.out.println(str1 == str3);System.out.println(str3 == str4);
}

输出:

image-20250310145941027

可以看见虽然这四个对象的值都是一样的,但是str1和str2是相等的,而str1和ster3以及str3和str4是不等的,为什么呢?

这里要提到一个String对象的字符串常量池

当使用String直接赋值创建实例化的时候,会先去字符串常量池寻找是否有这个对象

如果有这个对象则直接返回找到的字符串常量的地址,无需额外在堆内存里面开辟空间

所以在创建str2的时候先去字符串常量池找是否有”Word“的对象,找到了str1对象的值匹配,则返回的str1的地址,所以str1 == str2

具体的 JMM 内存

image-20250310151343445

由上图可以清晰得出这几个String对象的关系

基于上述原因,我们在比较两个字符串是否相等的时候一般调用equels方法,这个方法是String包装类来重写父类Object的equels方法,这样就可以比较值是否相等

public static void main(String[] args) {// 直接赋值String str1 ="Word";String str2 ="Word";// 构造器创建String str3 =new String("Word");String str4 =new String("Word");System.out.println(str1.equals(str2));System.out.println(str1.equals(str3));System.out.println(str3.equals(str4));
}

我们来看看String类里面的equals方法

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;
}

有几个关键节点

  • this == anObject:比较地址是否相等,如果相等肯定值相等,返回true
  • anObject instanceof String :如果不是String类型,则返回false
  • n == anotherString.value.length:比较长度是否相等,如果不相等直接返回false
  • while (n-- != 0):从后往前遍历比较,如果有一位不相等则返回false

String常用方法

方法 描述
public String() 创建一个值为空的对象
public String(String value) 创建一个值为 value 的对象
public String(char[] value) 将一个 char 类型数组转为字符串对象
public String(char[] value,int offset,int count) 将一个指定范围的 char 类型数组转为字符串对象
public String(byte[] bytes) 将一个 byte 类型数组转为字符串对象
public String(byte[] bytes,int offset,int count) 将一个指定范围的 byte 类型数组转为字符串对象
public int length() 返回字符串的长度
public boolean isEmpty() 判断字符串是否为空
public char charAt(int index) 返回字符串中指定位置的字符
public byte[] getBytes() 将字符串转为 byte 类型数组
public boolean equals(Object obj) 判断两个字符串是否相等
public boolean equalsIgnoreCase(String str) 判断两个字符串是否相等并且忽略大小写
public int compareTo(String str) 对两个字符串进行排序
public boolean startsWith(String str) 判断是否以指定的值开头
public boolean endsWith(String str) 判断是否以指定的值结尾
public int hashCode() 获取字符串的散列值
public int indexOf(String str) 从头开始查找指定字符的位置
public int indexOf(String str,int index) 从指定的位置开始查找指定字符的位置
public String substring(int index) 截取字符串从指定位置开始到结尾
public String substring(int index1,int index2) 截取字符串从指定位置开始到指定位置结束
public String concat(String str) 追加字符串
public String replaceAll(String str1,String str2) 替换字符串
public String[] split(String str) 用指定字符串对目标字符串进行分割,返回数组
public String toLowerCase() 将字符串转为小写
public String toUpperCase() 将字符串转为大写
public char[] toCharArray() 将字符串转为 char 数组

StringBuffer

实际开发中使用 String 会存在一个问题,String 对象一旦创建,值是不能修改的

诶,那我这样不就是修改了吗

public static void main(String[] args) {String str = "Hello, World!";System.out.println(str);str = "Word";System.out.println(str);
}

NoNoNo,这样不是在String对象修改

str = "Word";的效果是在堆内存里面创建一个新对象,然后把新对象的地址赋值给str变量,所以知识str变量的地址改变了

String 的值一旦修改,等于重新创建了一个对象进行赋值,而不能在原对象上进行修改

为什么 String 对象一旦修改,不能在原数据上进行修改,而是创建新对象重新赋值?

数组的特点:一旦创建,长度不能修改

因为 String 底层是一个字符数组,所以新的字符串的值无法追加到老字符串的后面,所以只能重新创建一个新的数组来存储新的字符串,所以说 String 的值不能修改(无法在原数据基础上进行修改)

创建的 String 对象,实际上是把字符串的内容存储到一个 char 数组中,String 底层是一个 char 数组

如果开发中需要对某个字符串进行频繁的修改,使用 String 就不合适了,会造成内存空间浪费的问题,如何解决?

使用 StringBuffer 来解决,StringBuffer 和 String 类似,底层也是用一个数组来存储字符串的值,并且默认长度是 16,既一个空的 StringBuffer 对象,数组长度为 16

当我们调用构造器创建一个 StringBuffer 对象时,数组长度就不是 16 了,而是根据当前对象的值来决定数组的长度,值的长度 + 16 作为数组的长度

无论创建的 String Buffer 对象是什么内容,都会预留 16 个长度,就是用来进行修改的

StringBuffer常用方法(和String差不多,实际就是比String更加节约内存)

方法 描述
public StringBuffer() 无参构造,创建一个空的 StringBuffer 对象
public StringBuffer(String str) 有参构造
public synchronized int length() 返回 StringBuffer 的长度
public synchronized char charAt(int index) 返回字符串中指定位置的字符
public synchronized StringBuffer append(String str) 追加字符
public synchronized StringBuffer delete(int start,int end) 删除指定区间内的字符
public synchronized StringBuffer deleteCharAt(int index) 删除指定位置的字符
public synchronized StringBuffer replace(int start,int end,String str) 将指定区间内的值替换为 str
public synchronized String substring(int start) 截取字符串从指定位置开始到结尾
public synchronized String substring(int start,int end) 截取字符串从指定位置开始到指定位置结束
public synchronized StringBuffer insert(int offset,String str) 向指定位置插入 str
public int indexOf(String str) 从头开始查找指定字符的位置
public int indexOf(String str,int index) 从指定位置开始查找指定字符的位置
public synchronized StringBuffer reverse() 进行反转
public synchronized String toString() 返回 StringBuffer 对应的 String

但是注意StringBuffer的方法很多有 synchronized 锁,因为StringBuffer具有可操作性

如果一个线程在读的时候另外一个线程在写,那么会导致数据错乱的安全问题

部分方法使用以及反馈:

public static void main(String[] args) {StringBuffer stringBuffer = new StringBuffer("Hello");// 添加stringBuffer.append(" World");System.out.println(stringBuffer);// 获取长度System.out.println(stringBuffer.length());// 获取字符System.out.println(stringBuffer.charAt(1));// 删除stringBuffer.delete(0, 5);System.out.println(stringBuffer);// 插入stringBuffer.insert(0, "Hello");System.out.println(stringBuffer);// 替换stringBuffer.replace(0, 5, "World");System.out.println(stringBuffer);// 截取字符串System.out.println(stringBuffer.substring(0, 5));// StringBuffer的容量System.out.println(stringBuffer.capacity());// 获取对应单词的起始位置System.out.println(stringBuffer.indexOf("d"));// 反转System.out.println(stringBuffer.reverse());
}

image-20250310223541278

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/897291.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

File类、字节字符流、InputStream和FileReader、OutputStream和FileWriter区别

DAY10.1 Java核心基础 File类 使用该类的构造函数可以创建一个对文件对象表示一个物理资源 File类常用方法方法 描述public File(String pathname) 根据路径创建对象public String getName() 获取文件名public String getParent() 获取文件所在的目录public File getParentFile…

FreeBSD 13.5 正式版发布 - 高性能开源 Unix 系统

FreeBSD 13.5 正式版发布 - 高性能开源 Unix 系统FreeBSD 13.5 正式版发布 - 高性能开源 Unix 系统 The Power To Serve 请访问原文链接:https://sysin.org/blog/freebsd-13/ 查看最新版。原创作品,转载请保留出处。 作者主页:sysin.orgFreeBSD 13.5-RELEASE 公告 日期:202…

FreeBSD 13.5 x86_64 OVF (sysin) - VMware 虚拟机模板

FreeBSD 13.5 x86_64 OVF (sysin) - VMware 虚拟机模板FreeBSD 13.5 x86_64 OVF (sysin) - VMware 虚拟机模板 The Power To Serve 请访问原文链接:https://sysin.org/blog/freebsd-13-ovf/ 查看最新版。原创作品,转载请保留出处。 作者主页:sysin.org2025 年 3 月 11 日,F…

2. 创建一个按钮组件

在deepseek中输入:创建一个vue组件 组件实现button的功能 预设4种颜色,分别对应:success: 绿色,危险按钮:红色,警告按钮:橘色,信息按钮:灰色 预设几个带icon的按钮,分别是:搜索,确定,取消,删除,上一页,下一页,分享,编辑 需要让调用该组件是可以自定义一些属性…

MySQL:CentOS 7 Docker 联网安装 MySQL

1. 创建mysql挂载目录 mkdir -p /home/data/mysql/config/ 配置目录挂载 mkdir -p /home/data/mysql/data/ 数据目录挂载 2. 在config目录下创建字符集文件 vim /home/data/mysql/config/my.cnf 填写 [mysqld] user=mysql character-set-server=utf8 [client] default-ch…

项目经理私藏!2025年10款小众但超实用的管理神器

在项目管理的江湖中,15 年的实战经验就像是一本活的百科全书,见证了无数项目的起起落落。想象一下,在一个大型建筑项目中,原本计划有序的施工突然因为材料供应不及时而陷入混乱,工期眼看着就要延误,成本也开始失控。这时候,一位经验丰富的项目经理凭借着他独特的管理工具…

SQLServer 死锁排查

适用于2012及以上版本一、创建扩展事件会话 CREATE EVENT SESSION [Deadlock_Monitor] ON SERVER ADD EVENT sqlserver.xml_deadlock_report ADD TARGET package0.event_file(SET filename=NDeadlock_Monitor.xel) WITH (STARTUP_STATE=ON); GO ALTER EVENT SESSION [Deadloc…

Eureka服务注册发现源码流程简析

一: 服务的注册客户端通过执行InstanceInfoReplicator#run()调用DiscoveryClient#register()发送http请求进行注册 InstanceInfoReplicator 是同于更新同步当前服务到服务端的任务实现 //A task for updating and replicating the local instanceinfo to the remote server.//…

高等数学笔记

唉...本蒟蒻也是要考研了, 目前目标是深圳大学, 想研究的方向偏算法多一点, 深度学习强化学习什么的, 我会尽最大努力了 9 做到一个新的问题,想起与过去某个问题类似。发现在解答中,对此类问题,以及工具和方法的理解是存在缺陷的,或者发现理解不够深刻。于是通过解决新的…

Scatter(A Distance-Guided Fuzzing For Heap-layout)

SCATTER Abstract 利用堆利用的方法为将受害者的chunk放在可以溢出的chunk之后。SCATTER使能够以无原始的方式以普通purpose程序中的堆溢出产生可剥削的堆布局。它先使用静态分析和动态检测来计算潜在的堆利用布局,然后设计由新操纵距离为指导的fuzz,该距离衡量了在堆布局空间…

使用 Pixi.js 插件实现探险者小游戏(二)

使用 Pixi.js 插件实现探险者小游戏(一)中我们学习了如何创建精灵图,这节我们要让精灵图动起来。 精灵图布局 游戏画面如下图所示,我们要生成一个围墙,探险者、恶魔、宝物都在这个围墙里面。探险者可以上下左右移动,恶魔只能上下移动,宝物是不动的。探险者与宝物被恶魔群…

Docker:CentOS 7 离线安装 docker-ce

0. 检查卸载已有docker 查看是否安装 docker yum list installed | grep docker 卸载docker yum remove docker docker-common container-selinux docker-selinux docker-engineyum remove -y docker-* 1. 下载安装包 要下载docker-18.06.x-ce版本,否则有些不支持 k8s。。请看…