Java-----String类

1.String类的重要性

经过了C语言的学习,我们认识了字符串,但在C语言中,我们表示字符串进行操作的话需要通过字符指针或者字符数组,可以使用标准库中提供的一系列方法对字符串的内容进行操作,但这种表达和操作数据的方法不太符合面向对象的思想,所以在Java中提供了String类。

2. 认识String类

349fdcf11fd44c86adeb4c3afe06257c.png

在Java中,String类是一种存储字符串数据类型的类。在Java中,String类属于引用数据类型,由String类创建的对象里面存的是引用。

2.1 字符串构造

在Java中,字符串的构造有很多种方式,常用的就以下三种。

public class Test {public static void main(String[] args) {//使用常量直接构造String s1="haha";System.out.println(s1);//直接new String对象String s2=new String("man");System.out.println(s2);//使用字符数组进行构造char[] array={'w','c','I','s'};String s3=new String(array);System.out.println(s3);}
}

运行代码

c6d84f77301a40f68ca6a9e5af781e07.png

2.2 深刻认识String类

我们知道String类的对象里面存的是引用,那字符串的内容具体是存在哪里的呢?

8e79d4e919a3486a85f57d07c554ef05.png

上图是String类里面的一些具体细节,发现里面有一个char[ ] value数组,所以字符串就是存储在这个数组中。

String类的堆栈图

b445ddec0a944569bb0851ed669065ac.png

2.3 String类的比较 

 1. 用 == 比较

当我们用 == 进行String类的对象进行比较时,是比较对象里面存的引用的值。

public class Test {public static void main(String[] args) {String s1="man";String s2=new String("man");String s3=s1;System.out.println(s1==s2);System.out.println(s1==s3);System.out.println(s2==s3);}
}

fa84433567e84ee3b4a94353aa8fe468.png

2. equal()方法比较

用equal方法比较String类的对象时,比较的是对象的字符串的内容是否相同。

public class Test {public static void main(String[] args) {String s1="haha";String s2=new String("man");String s3=s1;System.out.println(s1.equals(s2));System.out.println(s1.equals(s3));System.out.println(s2.equals(s3));}
}

66b23aedaa17494c9026e130be74c422.png

 3.int compareTo(String s)方法比较

1.当我们使用 int compareTo(String s) 方法比较时,比较的规则是:两个字符串对应位置上的的字母比较,直到比到对应的字母不同时,看哪个字母的ASCII值大,对应的那个字符串就长。就直接放回对应两个字母的ASCII值的差值。

2.当比较的两个字符串的长度不一样,一个长,一个短,假设短的字符串的长度为k,如果短的字符串的k个字符的内容与长字符串前k个字符相同,则放回两个字符串的差值。

public static void main(String[] args) {String s1 = new String("abc");String s2 = new String("ac");String s3 = new String("abc");String s4 = new String("abcdef");System.out.println(s1.compareTo(s2)); // 不同输出字符差值-1System.out.println(s1.compareTo(s3)); // 相同输出 0System.out.println(s1.compareTo(s4)); // 前k个字符完全相同,输出长度差值 -3
}

4. int compareToIgnoreCase(String str) 方法

与compareTo方式相同,但是忽略大小写比较
public static void main(String[] args) {String s1 = new String("abc");String s2 = new String("ac");String s3 = new String("ABc");String s4 = new String("abcdef");System.out.println(s1.compareToIgnoreCase(s2)); // 不同输出字符差值-1System.out.println(s1.compareToIgnoreCase(s3)); // 相同输出 0System.out.println(s1.compareToIgnoreCase(s4)); // 前k个字符完全相同,输出长度差值 -3
}

5.易错点(超级重点)

public static void main(String[] args) {String s1="hhh";String s2="hhh";System.out.println(s1==s2);//结果为true}

这时候因为s1和s2都是直接赋值,且内容一样,这时编译器会默认s1和s2指向同一块空间。

3.String类的常用方法

3.1 字符串查找

下图是一些Java中常用的字符串查找功能的方法。

2845c30522b04068b842a281a29d0e51.png

charAt(int index) 方法

用来查找字符串中指定位置上的字符

public class Test {public static void main(String[] args) {String str="manlebron";System.out.println(str.charAt(4));//输出e}
}

以上代码是查找字符串中下标为4的字符,是e。

int indexOf(int ch)方法

用来查找指定字符第一次出现的位置

public class Test {public static void main(String[] args) {String str="manlebron";System.out.println(str.indexOf('n'));}
}

int indexOf(int ch, int fromIndex)方法

用来在字符串中从fromIndex位置开始寻找第一次出现字符ch的位置

public class Test {public static void main(String[] args) {String str="manlebron";System.out.println(str.indexOf('l',2));}
}

int indexOf(String str) 方法

用来查找str第一次在字符串中出现的位置

public class Test {public static void main(String[] args) {String str="manlebron";System.out.println(str.indexOf("le"));}
}

由于剩下的方法用法差不多,就不 一 一 介绍了。

3.2 字符串转换

1. 数值和字符串之间的转换

public static void main(String[] args) {// 数字转字符String s1 = String.valueOf(1234);String s2 = String.valueOf(12.34);String s3 = String.valueOf(true);String s4 = String.valueOf(new Student("Hanmeimei", 18));System.out.println(s1);System.out.println(s2);System.out.println(s3);System.out.println(s4);System.out.println("=================================");// 字符串转数字// 注意:Integer、Double等是Java中的包装类型,这个后面会讲到int data1 = Integer.parseInt("1234");double data2 = Double.parseDouble("12.34");System.out.println(data1);System.out.println(data2);
}

2. 大小写转换

public static void main(String[] args) {String s1 = "hello";String s2 = "HELLO";// 小写转大写System.out.println(s1.toUpperCase());// 大写转小写System.out.println(s2.toLowerCase());
}

3.字符串和数组之间的转换

public static void main(String[] args) {String s = "hello";// 字符串转数组char[] ch = s.toCharArray();for (int i = 0; i < ch.length; i++) {System.out.print(ch[i]);}System.out.println();// 数组转字符串String s2 = new String(ch);System.out.println(s2);}

4. 格式化

public static void main(String[] args) {String s = String.format("%d-%d-%d", 2019, 9,14);System.out.println(s);
}

d3d6fccd700f44d89e9e7fdb29399ea1.png

 4.字符串替换

用来将一个字符串替换原有字符串中指定的一部分。

2f45c374355345d98c7a6fa373fdc4b8.png

 public static void main(String[] args) {String str = "helloworld" ;System.out.println(str.replaceAll("l", "_"));System.out.println(str.replaceFirst("l", "_"));}

26a876d777d6496caae43d5c0ed83fcd.png

 5. 字符串拆分------split方法

用来将一个字符串按指定的分割符将原来的字符串分割成多个字符串。

718cf82b7ebf4a519d8100c1d5db4b24.png

public static void main(String[] args) {String str = "hello world hello bit" ;String[] result = str.split(" ") ; // 按照空格拆分for(String s: result) {System.out.println(s);}}

d5f31b3d88f84c198c1d197d14d83d5c.png

 部分拆分

public static void main(String[] args) {String str = "hello world hello bit" ;String[] result = str.split(" ",3) ; // 按照空格拆分,分为3组for(String s: result) {System.out.println(s);}}

8b531713651743a78e07924d61bf94dc.png

注意事项:拆分是常用的操作,一定要重点掌握。另外,有些特殊的字符无法直接进行拆分,需要加上转移符号 ' \\ ' 。

如拆分IP地址

 如以下代码

public class Test {public static void main(String[] args) {String IP="192.168.1.1";String s[]=IP.split(".");for(String tmp:s){System.out.println(tmp);}}
}

运行代码

3a7ee3781af24bc8809b663597134aac.png

5.1 特殊字符的拆分 

1.点字符

我们发现什么输出都没有,这也就意味这分割没成功,因为 " . "是一个特殊的操作符,需要加上转义符号 " \\ " 。

修改如下

public class Test {public static void main(String[] args) {String IP="192.168.1.1";String s[]=IP.split("\\.");  //在 " . " 前加\\for(String tmp:s){System.out.println(tmp);}}
}

运行代码

baea70407e56426482cd13e3b292d940.png

 2. " \ " 字符

由于 \ 是一个整除符号,想要在表示 \ 是一个普通的斜杆,就必须在前面再加一个 \ 。

所以将其作为分割符时,要写成 "\\\\".

public static void main(String[] args) {String str="haha\\man\\what\\can\\I\\say?";for(String tmp:str.split("\\\\")){System.out.println(tmp);}}

9cf27251af6c4ce680e48db73c83eed9.png

5.2 多次拆分

当一个字符串中有多个字符时,我们可以进行多次拆分。

public static void main(String[] args) {String IP="192&man.168.1.1&haha";String s[]=IP.split("\\.");  //在 " . " 前加\\for(String tmp:s){for(String tmp2:tmp.split("&")){System.out.println(tmp2);}}}

运行代码:z

871d9e0ab3d54610bea27833cefdfd0c.png

我们也可以用 “ | ” 作为连字符,进行有多个字符的字符串进行拆分。

public static void main(String[] args) {String IP="192&man.168.1.1&haha";for(String tmp:IP.split("&|\\.")){System.out.println(tmp);}}

3c7b7106006547b58c924288a5d52d63.png

注意:不能在指定的分隔符前加上一个空格,因为空格也算一个字符。 

public static void main(String[] args) {String IP="192&man.168.1.1&haha";for(String tmp:IP.split("\\. | &")){System.out.println(tmp);}}

4e45573f3b13433d85e151861832f7f1.png

如上图所示,在分隔符前加一个空格,效果就变得不一样了。因为加了空格之后,分隔符就变成了“分隔符+空格”。

 5.3 小总结

1.字符 " | " , " * " , " + "都得加上转义字符,前面加上 " \\ " 。

2.  而如果是  " \ " ,那么就得写成 " \\\\ " 。

3. 如果一个字符串中有多个分隔符,可以用"|"作为连字符。

6. 字符串截取-----substring方法

1cebf5ee05d84e92aea9db21f1f94ae1.png

以上的substring方法是用来截取字符串中的一部分内容的。

代码演示

public static void main(String[] args) {String str = "helloworld" ;System.out.println(str.substring(5));System.out.println(str.substring(0, 5));//左开右闭 [0,5)}

89d6992fd98d4005b4076e265302bf16.png

7.其他方法---trim( )方法

trim( ) 方法是用来除去字符串两边的空格的,但并不会出去字符串里面的空格。

代码演示

public static void main(String[] args) {String str="    what can I say      ";String s=str.trim();System.out.println(s);}

a87728d3d2a84b209e8201ad7a3ce340.png

8. 字符串的不可变性

首先,我们要清楚,只要涉及到String类型的转变都不是在原字符串上进行的修改,原理是产生一个新的对象。 

 1.string类在设计时就是被设计为无法改变的,在String类中已经具体描述了,如下图:

638bc4671d634698aa2c4220f3779045.jpeg

64ae116509774a869d370285e03d7c9b.jpeg

从该图中还可以看出,字符串的内容是保存在char[ ] value 数组中的。

String类是如何设计成无法改变的呢?

一直有人误认为String类之所以无法被改变是因为String类被final修饰或者string类中的那个数组被final修饰,其实这些都是错误的。

因为一个类被final修饰只能表明这个类无法被继承,一个数组被final修饰,表示数组名存的引用无法被改变。这些都与String类无法被改变有联系。

真正的原因是,存放字符串的那个数组被private修饰了,且String类内没有提供任何方法来让外界去访问和使用该数组,所以就造成了字符串的不可变性。

10.字符串的修改

注意:我们要尽量避开对字符串的直接修改,因为String类是无法被改变的,所有的修改都会创建新的对象,会导致效率非常底下。

如以下代码:

public static void main(String[] args) {String s = "hello";s += " world";System.out.println(s); // 输出:hello world}

这段代码看似很简单,有看起来像直接对String类进行了修改。其实不然,

在这段代码的背后做了很多工作,先是创建了一个StringBuilder对象,在原来s中字符串的内容存到StringBuilder对象里面,然后在对StringBuilder对象进行了修改,然后再通过toString()方法转换为String类型,最后再放回一个新的String类的对象。

如下图

a4725defd9bd435ebf9cf06b1b1c59f9.jpeg

这里创建了很多临时变量,就导致了效率低下。

因此我们要尽量避免对String类的直接改变,如果要修改建议尽量 使用StringBuffer或者StringBuilder。

11.StringBuilder和StringBuffer

由于String类型无法直接被改变,再Java中提供了StringBuilder和StringBuffer类,这两个类也是可以存储字符串的,但可以直接对字符串修改的。

public static void main(String[] args) {StringBuilder stringBuilder=new StringBuilder("haha ");System.out.println(stringBuilder.append("man"));StringBuffer stringBuffer=new StringBuffer("what can I say");stringBuffer.append("?");System.out.println(stringBuffer);}

e4eea03714af4b84b299daf7e96a6f78.png

其实 StringBuilder和StringBuffer的用法很相似,就一个区别。

ba97e3bcdcdd49abb92ae467b0b55ce3.png

如上图StringBuffer中多了一个synchronized,这个可以理解为一把锁,在多线程的情况下可以保证安全。

而StringBuilder主要是在单线程情况下使用。

StringBuilder和StringBuffer和String的区别

1. String的内容不可修改,StringBuffer与StringBuilder的内容可以修改.

2.StringBuffer与StringBuilder大部分功能是相似的
3.StringBuffer采用同步处理,属于线程安全操作;而StringBuilder未采用同步处理,属于线程不安
全操作。

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

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

相关文章

Go语言交叉编译

Golang 支持交叉编译&#xff0c; 在一个平台上生成然后再另外一个平台去执行。 以下面代码为例 build ├── main.go ├── go.mod main.go内容 package mainimport "fmt"func main() {fmt.Println("hello world") }windows系统上操作 1.cmd窗口编译…

【OCPP】ocpp1.6协议第4.2章节BootNotification的介绍及翻译

目录 4.2、BootNotification-概述 Boot Notification 消息 BootNotification 请求消息 BootNotification 响应消息 使用场景 触发 BootNotification 的条件 实现示例 构建请求消息 发送请求并处理响应 小结 4.2、BootNotification-原文译文 4.2.1、被中央系统接受之…

ios v品会 api-sign算法

vip品会 api-sign算法还原 ios入门案例 视频系列 IOS逆向合集-前言哔哩哔哩bilibili 一、ios难度与安卓对比 这里直接复制 杨如画大佬的文章的内容&#xff1a; ios难度与安卓对比 很多人说ios逆向比安卓简单&#xff0c;有以下几个原因 1 首先就是闭源&#xff0c;安卓开源…

无人售货机零售业务成功指南:从市场分析到创新策略

在科技驱动的零售新时代&#xff0c;无人售货机作为一种便捷购物解决方案&#xff0c;正逐步兴起&#xff0c;它不仅优化了消费者体验&#xff0c;还显著降低了人力成本&#xff0c;提升了运营效能。开展这项业务前&#xff0c;深入的市场剖析不可或缺&#xff0c;需聚焦消费者…

ch4网络层---计算机网络期末复习(持续更新中)

网络层概述 将分组从发送方主机传送到接收方主机 发送方将运输层数据段封装成分组 接收方将分组解封装后将数据段递交给运输层网络层协议存在于每台主机和路由器上 路由器检查所有经过它的IP分组的分组头 注意路由器只有3层(网络层、链路层、物理层) 网络层提供的服务 一…

discuz如何添加主导航

大家好&#xff0c;今天教大家怎么样给discuz添加主导航。方法其实很简单&#xff0c;大家跟着我操作既可。一个网站的导航栏是非常重要的&#xff0c;一般用户进入网站的第一印象就是看网站的导航栏。如果大家想看效果的话可以搜索下网创有方&#xff0c;或者直接点击查看效果…

SpringCloud Feign用法

1.在目标应用的启动类上添加开启远程fein调用注解&#xff1a; 2.添加一个feign调用的interface FeignClient("gulimall-coupon") public interface CouponFeignService {PostMapping("/coupon/spubounds/save")R save(RequestBody SpuBondTo spuBounds);…

C++语言学习(七)—— 继承、派生与多态(一)

目录 一、派生类的概念 1.1 定义派生类的语法格式 1.1.1 定义单继承派生类 1.1.2 定义多继承派生类 1.2 继承方式 二、公有继承 三、派生类的构造和析构 四、保护成员的引入 五、改造基类的成员函数 六、派生类与基类同名成员的访问方式 七、私有继承和保护继承 7.…

zdppy_api 中间件请求原理详解

单个中间件的逻辑 整体执行流程&#xff1a; 1、客户端发起请求2、中间件拦截请求&#xff0c;在请求开始之前执行业务逻辑3、API服务接收到中间件处理之后的请求&#xff0c;和数据库交互&#xff0c;请求数据4、数据库返回数据5、API处理数据库的数据&#xff0c;然后给客户…

探索数据结构:快速排序与归并排序的实现与优化

✨✨ 欢迎大家来到贝蒂大讲堂✨✨ &#x1f388;&#x1f388;养成好习惯&#xff0c;先赞后看哦~&#x1f388;&#x1f388; 所属专栏&#xff1a;数据结构与算法 贝蒂的主页&#xff1a;Betty’s blog 1. 快速排序 1.1. 算法思想 **快速排序(Quick Sort)**是Hoare于1962年…

【数据结构】穿梭在二叉树的时间隧道:顺序存储的实现

专栏引入 哈喽大家好&#xff0c;我是野生的编程萌新&#xff0c;首先感谢大家的观看。数据结构的学习者大多有这样的想法&#xff1a;数据结构很重要&#xff0c;一定要学好&#xff0c;但数据结构比较抽象&#xff0c;有些算法理解起来很困难&#xff0c;学的很累。我想让大家…

AI程序员来了,大批码农要失业

根据GitHub发布的《Octoverse 2021年度报告》&#xff0c;2021年中国有755万程序员&#xff0c;排名全球第二。 ChatGPT的出现&#xff0c;堪比在全球互联网行业点燃了一枚“核弹”&#xff0c;很多人都会担心“自己的工作会不会被AI取代”。 而2024年的AI进展速度如火箭般&am…

getway整合sentinel流控降级

3. 启动sentinel控制台增加流控规则&#xff1a; 根据API分组进行流控&#xff1a; 1.设置API分组&#xff1a; 2.根据API分组进行流控&#xff1a; 自定义统一异常处理&#xff1a; nginx负载配置&#xff1a;

vue-router 源码分析——2. router-link 组件是如何实现导航的

这是对vue-router 3 版本的源码分析。 本次分析会按以下方法进行&#xff1a; 按官网的使用文档顺序&#xff0c;围绕着某一功能点进行分析。这样不仅能学习优秀的项目源码&#xff0c;更能加深对项目的某个功能是如何实现的理解。这个对自己的技能提升&#xff0c;甚至面试时…

德人合科技——@天锐绿盾 | -文档透明加密系统

天锐绿盾文档透明加密系统是一种先进的数据安全解决方案&#xff0c;旨在保护企业和组织的敏感信息&#xff0c;防止未经授权的访问和泄漏。 PC地址&#xff1a; https://isite.baidu.com/site/wjz012xr/2eae091d-1b97-4276-90bc-6757c5dfedee 以下是该系统的一些关键特点和功…

【读书笔记】曼陀罗思考法

目录 1 起源2 路径示例——人生规划设计 3 分类3.1 扩展型“扩展型”曼陀罗——使用方法 3.2 围绕型 4 注意事项 1 起源 曼陀罗在梵文中意味着“圣地”&#xff0c;象征着宇宙的秩序和内心的神圣结构。 “曼陀罗思考法”&#xff0c;是由日本学者今泉浩晃发明的方法&#xff…

【计算机毕设】基于SpringBoot的中小企业设备管理系统设计与实现 - 源码免费(私信领取)

免费领取源码 &#xff5c; 项目完整可运行 &#xff5c; v&#xff1a;chengn7890 诚招源码校园代理&#xff01; 1. 研究目的 在中小企业中&#xff0c;设备管理是确保生产和运营效率的重要环节。传统的设备管理通常依赖于手工记录和人工管理&#xff0c;容易导致数据不准确、…

LLM的基础模型4:初识Embeddings

大模型技术论文不断&#xff0c;每个月总会新增上千篇。本专栏精选论文重点解读&#xff0c;主题还是围绕着行业实践和工程量产。若在某个环节出现卡点&#xff0c;可以回到大模型必备腔调或者LLM背后的基础模型新阅读。而最新科技&#xff08;Mamba,xLSTM,KAN&#xff09;则提…

12-学生们参加各科测试的次数(高频 SQL 50 题基础版)

12-学生们参加各科测试的次数 -- 学生表中&#xff0c;id是唯一的&#xff0c;将他作为主表 -- CROSS JOIN产生了一个结果集&#xff0c;该结果集是两个关联表的行的乘积 -- 2行表,与3行表使用cross join,得到2*36行数据 select st.student_id, st.student_name,su.subject_na…

【软件测试】自动化测试如何管理测试数据

前言 在之前的自动化测试框架相关文章中&#xff0c;无论是接口自动化还是UI自动化&#xff0c;都谈及data模块和config模块&#xff0c;也就是测试数据和配置文件。 随着自动化用例的不断增加&#xff0c;需要维护的测试数据也会越来越多&#xff0c;维护成本越来越高&#…