【Java SE】带你在String类世界中遨游!!!

🌹🌹🌹我的主页🌹🌹🌹
🌹🌹🌹【Java SE 专栏】🌹🌹🌹
🌹🌹🌹上一篇文章:带你走近Java的抽象类与接口🌹🌹🌹
文章目录
- 1. String类的重要性
- 2. String类常用方法
- 2.1 字符串构造
- 2.2 String对象的比较
- 2.3 字符串查找
- 2.4 转化
- 2.5 字符串替换
- 2.6 字符串拆分
- 2.7 字符串截取
- 2.8 字符串的不可变性
- 2.11 字符串修改
- 3.StringBuilder和StringBuffer
- 3.1 StringBuilder的介绍
1. String类的重要性
在C语言中已经涉及到字符串了,但是在C语言中要表示字符串只能使用字符数组或者字符指针,可以使用标准库提供的字符串系列函数完成大部分操作,但是这种将数据和操作数据方法分离开的方式不符合面相对象的思想,而字符串应用又非常广泛,因此Java语言专门提供了String类。
2. String类常用方法
2.1 字符串构造
String类提供的构造方式非常多,常用的就以下三种:
1.使用常量串构造,也称字符串赋值
String str = "hello";
2.直接newString对象
String str1 = new String("hello,world");
3.使用字符数组进行构造
char[] array = {'1','2','3','4'};
String str2 = new String(array);
将数组名作为形参传到String的构造函数之后,调用了数组的复制方法copyof,然后返回的类型是String类型。

【注意】
- String是引用类型,内部并不存储字符串本身,在String类的实现源码中,String类实例变量如下:

字符串中的内容实际存储在value[]数组当中。
字符串是引用类型,并不直接存储字符串的内容,而是存储的是引用变量的地址。
以下代码和画图演示可以证明:
public static void main(String[] args) {My_String.fun();String str1 = new String("1234");String str2 = new String("12");String str3 = str1;System.out.println(str1.length());System.out.println(str3.isEmpty());}
str1的引用变量的地址赋值给了str3,此时的str3引用变量存储的是str1的地址,这样也可以通过str3引用变量来指向str1中的字符串的内容。
上述的打印结果分别是4,和false则可以证明这个结论。

结果显示,结论正确。
就接下来看看画图演示:

2. 在Java中“”引起来的也是String类型对象。
System.out.println(str1.length());System.out.println(str3.isEmpty());System.out.println("hello".length());

2.2 String对象的比较
字符串的比较是常见操作之一,比如:字符串排序。Java中总共提供了4中方式:
- "== "比较是否引用同一个对象
对于简单类型""是比较数值的大小,而对于引用类型“”是比较引用变量的地址。
public static void main(String[] args) {//简单类型int a = 10;int b = 10;//引用类型String str1 = new String("abcdefg");String str2 = new String("abcdefg");//比较简单类型System.out.println(a == b);//true false//比较引用类型System.out.println(str1 == str2);}}

结果显示:在基本类型中比较的是数值,而在引用类型当中比较的是地址。
2. boolean equals(Object anObject) 方法:按照字典序比较:
比较返回类型为boolean类型,相同则返回true不相同则返回false
字典序:字符大小的顺序,字符大小:字符返回的ASCII值。
String类重写了父类Object中equals方法,Object中equals默认按照==比较:
public boolean equals(Object obj) {return (this == obj);}
因为object中equals默认按照==比较,所以我们要在String类中重写equals方法:
//在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;}
接下来我们来通过str1.equals(str2)比较引用类型的内容:
public static void main(String[] args) {String str1 = new String("abcdefg");String str2 = new String("abcdefg");String str3 = new String("ABCDEFG");System.out.println(str1.equals(str2));System.out.println(str1.equals(str3));}

通过重写equals方法,我们就可以用字典序来比较字符串的大小了。
在比较字符串的大小的时候:
第一步:我们通过字典序来比较。
第二步:当字典序相同的时候,我们可以通过字符串的长度来比较。
3. int compareTo(String s) 方法: 按照字典序进行比较:
这个和equals不同的是,返回类型不是boolean类型而是int类型,比较方式:
- 先按照字典次序大小比较,如果出现不等的字符,直接返回这两个字符的大小差值
- 如果前k个字符相等(k为两个字符长度最小值),返回值两个字符串长度差值
public static void main(String[] args) {String str1 = new String("abcdefg");String str2 = new String("abcdefg");String str3 = new String("ABCDEFG");System.out.println(str1.compareTo(str2));System.out.println(str1.compareTo(str3));}

4. int compareToIgnoreCase(String str) 方法:与compareTo方式相同,但是忽略大小写比较:
public static void main(String[] args) {String str1 = new String("abcdefg");String str2 = new String("abcdefg");String str3 = new String("ABCDEFG");String str4 = new String("zhangsan");System.out.println(str1.compareToIgnoreCase(str2));System.out.println(str1.compareToIgnoreCase(str3));System.out.println(str1.compareToIgnoreCase(str4));}

2.3 字符串查找
字符串查找也是字符串中非常常见的操作,String类提供的常用查找的方法:
- public char charAt(int index)从字符串中拿到一个字符。
在String类中的方法是这么实现的。

自己来实现一下这个方法:
public static void main(String[] args) {String str1 = new String("abcdef");char ch = str1.charAt(0);//'a'char ch1 = str1.charAt(1);//'b'char ch2 = str1.charAt(-1);//抛异常char ch3 = str1.charAt(6);//抛异常System.out.println(ch);System.out.println(ch1);System.out.println(ch2);System.out.println(ch3);}
- int indexOf(int ch) 返回字符的下标,找不到就返回-1,从头开始一个一个找。
我们来实现一下这个方法:
public static void main(String[] args) {String str1 = new String("abcdef");System.out.println(str1.indexOf('a'));System.out.println(str1.indexOf('b'));System.out.println(str1.indexOf('z'));}

3. int indexOf(int ch, intfromIndex) 从指定位置开始找这个字符,找到返回下标,找不到就返回-1。
我们来实现这个方法:
public static void main(String[] args) {String str = new String("hello");System.out.println(str.indexOf('l', 3));}

4. int indexOf(String str) 从头开始在字符串A找字符串B,找到了返回字符串A中字符串B的第一个下标,比如:字符串A"hello",字符串B"llo"则返回"llo"在字符串A的下标,找不到就返回-1.
我们来实现这个方法:|
public static void main(String[] args) {String str = new String("hello");System.out.println(str.indexOf("llo"));System.out.println(str.indexOf("all"));}

5 . int indexOf(String str, intfromIndex) 在指定位置从字符串A中找字符串B,找到还是一样返回字符串A中字符串B的第一个下标。找不到返回-1.
我们来实现这个方法:
public static void main(String[] args) {String str = new String("hello");System.out.println(str.indexOf("llo", 2));System.out.println(str.indexOf("llo", 4));}

6. int lastIndexOf(int ch) 从字符串最后的位置找目标字符,找到就返回其下标,找不到就返回-1.
我们来实现这个方法:
public static void main(String[] args) {String str = new String("hello");System.out.println(str.lastIndexOf('o'));System.out.println(str.lastIndexOf('a'));}

**【注意】**这个找到的下标还是从前往后数的下标,而不是从后往前数的。
7. int lastIndexOf(int ch, intfromIndex) 这个是从指定位置,往后找这个字符,找到返回其下标,找不到就返回-1.
我们来实现这个方法:
public static void main(String[] args) {String str = new String("hello");System.out.println(str.lastIndexOf('l', 4));System.out.println(str.lastIndexOf('l', 1));

8. int lastIndexOf(String str) 从后往前在字符串A中找字符串B,找到了返回字符串A中字符串B的第一个下标,找不到就返回-1.
我们来实现这个方法:
public static void main(String[] args) {String str = new String("hello");System.out.println(str.lastIndexOf("llo"));System.out.println(str.lastIndexOf("lle"));

9. int lastIndexOf(String str, intfromIndex) 从指定位置从后往前在字符串A中找字符串B,找到了返回字符串A中字符串B的第一个下标,找不到就返回-1.
我们来实现这个方法:
public static void main(String[] args) {String str = new String("hello");System.out.println(str.lastIndexOf("llo", 4));System.out.println(str.lastIndexOf("llo", 1));

2.4 转化
1. 数值和字符串转化
public static void main(String[] args) {//数字转字符串String str = String.valueOf(123);System.out.println(str);//字符串转数字Integer ii = Integer.valueOf("123");System.out.println(ii);}
字符串转化其他类型,构成了一个重载方法:String.valueOf()

其他类型转化String类型:
Integer.valueOf()
Float.valueOF()
…
2. 大小写转换
public static void main(String[] args) {String str = new String("abc");String str1 = new String("ABC");//小写转化为大写System.out.println(str.toUpperCase());//大写转化小写System.out.println(str1.toLowerCase());}

3. 字符串转数组
字符串转化数组
toCharArray()
public static void main(String[] args) {String str ="abc";char[] chars = str.toCharArray();System.out.println(Arrays.toString(chars));}

数组转化为字符串
public static void main(String[] args) {char[] chars = {'1','2','3'};String str = new String(chars);System.out.println(str);}
4.格式化
String.format()
public static void main(String[] args) {String s = String.format("%d-%d-%d", 2019, 9,14);System.out.println(s);}
2.5 字符串替换
使用一个指定的新的字符串替换掉已有的字符串数据,可用的方法如下:
1.String replaceAll(String regex, String replacement) 替换所有指定的内容
String regex:被替换的内容
String replacement:替换的内容
public static void main(String[] args) {String str = "helloworld";System.out.println(str.replaceAll("l", "+"));}
2.String replaceFirst(String regex, String replacement) 替换首个内容
String regex:在被替换的内容中出现第一次的内容
String replacement:替换的内容
public static void main(String[] args) {String str = "helloworld";System.out.println(str.replaceFirst("l", "+"));
}

注意事项: 由于字符串是不可变对象, 替换不修改当前字符串, 而是产生一个新的字符串.
2.6 字符串拆分
可以将一个完整的字符串按照指定的分隔符划分为若干个子字符串。
可用方法如下:
1.String[] split(String regex) 将字符串全部拆分,将字符串拆分,用字符串数组来接收。
String regex:以指定的格式拆分
public static void main(String[] args) {String str = "hello world java SE";String[] ret = str.split(" ");for (String s:ret) {System.out.println(s);}}
2.String[] split(String regex, int limit) 将字符串以指定的格式,拆分为limit组
String regex:以指定的格式拆分
int limit:拆分几组
public static void main(String[] args) {String str = "hello world java SE";String[] ret = str.split(" ",2);for (String s:ret) {System.out.println(s);}}
注意事项:
- 字符"|“,”*“,”+"都得加上转义字符,前面加上 “\” .
- 而如果是 “” ,那么就得写成 “\\” .
- 如果一个字符串中有多个分隔符,可以用"|"作为连字符.
2.7 字符串截取
从一个完整的字符串之中截取出部分内容。可用方法如下:
1.String substring(int beginIndex) 从指定位置截取到结尾
int beginIndex:指定位置
String str = "helloworld" ;
System.out.println(str.substring(5));
2.String substring(int beginIndex, int endIndex) 截取部分内容
int beginIndex:截取的开始位置
int endIndex: 截取的结束位置
String str = "helloworld" ;
System.out.println(str.substring(0, 5));
注意事项:
- 索引从0开始
- 注意前闭后开区间的写法, substring(0, 5) 表示包含 0 号下标的字符, 不包含 5 号下标
2.8 字符串的不可变性
String是一种不可变对象. 字符串中的内容是不可改变。字符串不可被修改,是因为:
1. String类在设计时就是不可改变的,String类实现描述中已经说明了:


String类中的字符实际保存在内部维护的value字符数组中,该图还可以看出:
- String类被final修饰,表明该类不能被继承
- value被修饰被final修饰,只能引用当前初始化好的对象不能引用其他对象,但是其引用空间中的内容可以修改。
2. 所有涉及到可能修改字符串内容的操作都是创建一个新对象,改变的是新对象
最后总结一下:字符串不可变是因为其内部保存字符的数组被final修饰了,因此不能改变。这种说法是错误的。
字符串不可变的原因有两点:
1.String类被final修饰,表明该类不能被继承
2.value被修饰被final修饰,只能引用当前初始化好的对象不能引用其他对象,但是其引用空间中的内容可以修改
2.11 字符串修改
注意:尽量避免直接对String类型对象进行修改,因为String类是不能修改的,所有的修改都会创建新对象,效率非常低下。
我们通过拼接符“+”确实可以对字符串进行修改,但是这样的效率太慢了。
public static void main(String[] args) {
String s = "hello";
s += " world";
System.out.println(s); // 输出:hello world
}
但是这种方式不推荐使用,因为其效率非常低,中间创建了好多临时对象。
关于这些临时变量怎么可以看到,我们可以通过反汇编的方式可以看到:


根据上面的图片我们可以看到有两个新的类:StringBuilder和StringBuffer
在这两个类中字符串是可以改变的。
接下来我们来看看这两个类把!
3.StringBuilder和StringBuffer
3.1 StringBuilder的介绍
由于String的不可更改特性,为了方便字符串的修改,Java中又提供StringBuilder和StringBuffer类。这两个类大部分功能是相同的,这里介绍 StringBuilder常用的一些方法:


从上述方法可以看出:String和StringBuilder最大的区别在于String的内容无法修改,而StringBuilder的内容可以修改。频繁修改字符串的情况考虑使用StringBuilder。
这些方法我就不一一解释了,和上述String类方法差不多。
结尾:
希望大家可以给我点点关注,点点赞,你们的支持就是我的最大鼓励。🌹🌹🌹🌹🌹🌹🌹🌹🌹🌹🌹🌹🌹🌹
相关文章:
【Java SE】带你在String类世界中遨游!!!
🌹🌹🌹我的主页🌹🌹🌹 🌹🌹🌹【Java SE 专栏】🌹🌹🌹 🌹🌹🌹上一篇文章:带你走近Java的…...
Android: ListView + ArrayAdapter 简单应用
容器与适配器: http://t.csdnimg.cn/ZfAJ7 activity_main.xml <?xml version"1.0" encoding"utf-8"?> <LinearLayout xmlns:android"http://schemas.android.com/apk/res/android"xmlns:app"h…...
前端:实现二级菜单(点击实现二级菜单展开)
效果 代码 <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8"><meta http-equiv"X-UA-Compatible" content"IEedge"><meta name"viewport" content"widthdevice-width, i…...
Spark-java版
SparkContext初始化 相关知识 SparkConf 是SparkContext的构造参数,储存着Spark相关的配置信息,且必须指定Master(比如Local)和AppName(应用名称),否则会抛出异常;SparkContext 是程序执行的入口…...
RabbitMQ消息模型之Work Queues
Work Queues Work Queues,也被称为(Task Queues),任务模型,也是官网给出的第二个模型,使用的交换机类型是直连direct,也是默认的交换机类型。当消息处理比较耗时的时候,可能生产消息…...
vue3+ts 实现时间间隔选择器
需求背景解决效果视频效果balancedTimeElement.vue 需求背景 实现一个分片的时间间隔选择器,需要把显示时间段显示成图表,涉及一下集中数据转换 [“02:30-05:30”,“07:30-10:30”,“14:30-17:30”]‘[(2,5),(7,10),(14,17)]’[4, 5, 6, 7, 8, 9, 10, …...
PTA 魔法优惠券
7-83 魔法优惠券 分数 25 全屏浏览题目 作者 陈越 单位 浙江大学 在火星上有个魔法商店,提供魔法优惠券。每个优惠劵上印有一个整数面值K,表示若你在购买某商品时使用这张优惠劵,可以得到K倍该商品价值的回报!该商店还免费赠送…...
P8A110-A120经典赛题
Web应用程序SQL Inject安全攻防 任务环境说明: 服务器场景:WebServ2003(用户名:administrator;密码:空)服务器场景操作系统:Microsoft Windows2003 Server 服务器场景安装服务/工…...
文件基础知识
计算机中的流:在C语言中将通过输入/输出设备(键盘、内存、显示器、网络等)之间的数据传输抽象表述为“流”。 1、文本流和二进制流 在文本流中输入输出的数据是一系列的字符,可以被修改在二进制流中输入输出数据是一系列字节&am…...
二叉树OJ题之二
今天我们一起来看一道判断一棵树是否为对称二叉树的题,力扣101题, https://leetcode.cn/problems/symmetric-tree/ 我们首先先来分析这道题,要判断这道题是否对称,我们首先需要判断的是这颗树根节点的左右子树是否对称࿰…...
MySql表中添加emoji表情
共五处需要修改。 语句执行修改: ALTER TABLE xxxxx CONVERT TO CHARACTER SET utf8mb4;...
【新手解答1】深入探索 C 语言:变量名、形参 + 主调函数、被调函数 + 类和对象 + 源文件(.c 文件)、头文件(.h 文件)+ 库
C语言的相关问题解答 写在最前面目录 问题1变量名与变量的关系与区别变量和数据类型形参(形式参数)的概念 问题2解析:主调函数和被调函数延伸解析:主调函数对于多文件程序的理解总结 问题3类和对象变量和数据类型变量是否为抽象的…...
2023最新的软件测试热点面试题(答案+解析)
📢专注于分享软件测试干货内容,欢迎点赞 👍 收藏 ⭐留言 📝 如有错误敬请指正!📢交流讨论:欢迎加入我们一起学习!📢资源分享:耗时200小时精选的「软件测试」资…...
NCo3.1(08) - Nco3 服务器端编程
本篇博文不再重复ABAP调用外部服务器的基础,只介绍 NCo3 开发的过程和要点。需要了解相关知识点的小伙伴们自行参考: SAP接口编程 之JCo3.0系列(06) - Jco服务器端编程 PyRFC 服务器端编程要点 创建项目 新建一个 Console 项目,选择 .Net …...
【代码随想录】算法训练计划36
贪心 1、435. 无重叠区间 题目: 给定一个区间的集合 intervals ,其中 intervals[i] [starti, endi] 。返回 需要移除区间的最小数量,使剩余区间互不重叠 。 思路: 贪心,重叠个数,和射气球一样,重叠区间…...
Python (十五) 面向对象之多继承问题
程序员的公众号:源1024,获取更多资料,无加密无套路! 最近整理了一波电子书籍资料,包含《Effective Java中文版 第2版》《深入JAVA虚拟机》,《重构改善既有代码设计》,《MySQL高性能-第3版》&…...
广域网加速技术
摘要: 随着企业数字化转型快速发展,越来越多企业将IT系统、应用和服务部署到云上,以实现更高效、灵活的管理和使用。这就对广域网提出了更高的要求,而广域网线路往往存在带宽费用昂贵、服务质量不可靠等问题。为了改善用户体验&am…...
构建智能医患沟通:陪诊小程序开发实战
在医疗科技的浪潮中,陪诊小程序的开发成为改善医患沟通的创新途径之一。本文将介绍如何使用Node.js和Express框架构建一个简单而强大的陪诊小程序,实现患者导诊和医生咨询功能。 1. 安装Node.js和Express 首先确保已安装Node.js,然后使用以…...
插入区间[中等]
优质博文:IT-BLOG-CN 一、题目 给你一个无重叠的 ,按照区间起始端点排序的区间列表。在列表中插入一个新的区间,你需要确保列表中的区间仍然有序且不重叠(如果有必要的话,可以合并区间)。 示例 1&#x…...
Android Bitmap 模糊效果实现 (二)
文章目录 Android Bitmap 模糊效果实现 (二)使用 Vukan 模糊使用 RenderEffect 模糊使用 GLSL 模糊RS、Vukan、RenderEffect、GLSL 效率对比 Android Bitmap 模糊效果实现 (二) 本文首发地址 https://blog.csdn.net/CSqingchen/article/details/134656140 最新更新地址 https:/…...
Frozen-Flask :将 Flask 应用“冻结”为静态文件
Frozen-Flask 是一个用于将 Flask 应用“冻结”为静态文件的 Python 扩展。它的核心用途是:将一个 Flask Web 应用生成成纯静态 HTML 文件,从而可以部署到静态网站托管服务上,如 GitHub Pages、Netlify 或任何支持静态文件的网站服务器。 &am…...
ArcGIS Pro制作水平横向图例+多级标注
今天介绍下载ArcGIS Pro中如何设置水平横向图例。 之前我们介绍了ArcGIS的横向图例制作:ArcGIS横向、多列图例、顺序重排、符号居中、批量更改图例符号等等(ArcGIS出图图例8大技巧),那这次我们看看ArcGIS Pro如何更加快捷的操作。…...
Mysql中select查询语句的执行过程
目录 1、介绍 1.1、组件介绍 1.2、Sql执行顺序 2、执行流程 2.1. 连接与认证 2.2. 查询缓存 2.3. 语法解析(Parser) 2.4、执行sql 1. 预处理(Preprocessor) 2. 查询优化器(Optimizer) 3. 执行器…...
使用Spring AI和MCP协议构建图片搜索服务
目录 使用Spring AI和MCP协议构建图片搜索服务 引言 技术栈概览 项目架构设计 架构图 服务端开发 1. 创建Spring Boot项目 2. 实现图片搜索工具 3. 配置传输模式 Stdio模式(本地调用) SSE模式(远程调用) 4. 注册工具提…...
20个超级好用的 CSS 动画库
分享 20 个最佳 CSS 动画库。 它们中的大多数将生成纯 CSS 代码,而不需要任何外部库。 1.Animate.css 一个开箱即用型的跨浏览器动画库,可供你在项目中使用。 2.Magic Animations CSS3 一组简单的动画,可以包含在你的网页或应用项目中。 3.An…...
LangFlow技术架构分析
🔧 LangFlow 的可视化技术栈 前端节点编辑器 底层框架:基于 (一个现代化的 React 节点绘图库) 功能: 拖拽式构建 LangGraph 状态机 实时连线定义节点依赖关系 可视化调试循环和分支逻辑 与 LangGraph 的深…...
tomcat指定使用的jdk版本
说明 有时候需要对tomcat配置指定的jdk版本号,此时,我们可以通过以下方式进行配置 设置方式 找到tomcat的bin目录中的setclasspath.bat。如果是linux系统则是setclasspath.sh set JAVA_HOMEC:\Program Files\Java\jdk8 set JRE_HOMEC:\Program Files…...
前端中slice和splic的区别
1. slice slice 用于从数组中提取一部分元素,返回一个新的数组。 特点: 不修改原数组:slice 不会改变原数组,而是返回一个新的数组。提取数组的部分:slice 会根据指定的开始索引和结束索引提取数组的一部分。不包含…...
Xela矩阵三轴触觉传感器的工作原理解析与应用场景
Xela矩阵三轴触觉传感器通过先进技术模拟人类触觉感知,帮助设备实现精确的力测量与位移监测。其核心功能基于磁性三维力测量与空间位移测量,能够捕捉多维触觉信息。该传感器的设计不仅提升了触觉感知的精度,还为机器人、医疗设备和制造业的智…...
绕过 Xcode?使用 Appuploader和主流工具实现 iOS 上架自动化
iOS 应用的发布流程一直是开发链路中最“苹果味”的环节:强依赖 Xcode、必须使用 macOS、各种证书和描述文件配置……对很多跨平台开发者来说,这一套流程并不友好。 特别是当你的项目主要在 Windows 或 Linux 下开发(例如 Flutter、React Na…...
