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.mzph.cn/bicheng/20462.shtml

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

相关文章

沟通程序化(1):跟着鬼谷子学沟通—“飞箝”之术

沟通的基础需要倾听&#xff0c;但如果对方听不进你的话&#xff0c;即便你说的再有道理&#xff0c;对方也很难入心。让我们看看鬼谷子的“飞箝”之术能给我们带来什么样的启发吧&#xff01; “飞箝”之术&#xff0c;源自中国古代兵法家、纵横家鼻祖鬼谷子的智慧&#xff0…

SpringBootWeb 篇-深入了解 Spring 异常处理、事务管理和配置文件参数配置化、yml 配置文件

&#x1f525;博客主页&#xff1a; 【小扳_-CSDN博客】 ❤感谢大家点赞&#x1f44d;收藏⭐评论✍ 文章目录 1.0 配置文件 1.1 yml 配置文件 1.2 参数配置化 1.2.1 使用 Value 注解注入单个配置参数 1.2.2 使用 ConfigurationProperties 注解将一组相关配置参数注入到一个类中…

discuz论坛怎么修改备案信息

大家好&#xff0c;今天给大家分享下discuz如何填写备案信息并且展示在网站首页。大家都知道国内网站都需要备案&#xff0c;不通过备案的网站上是没办法通过域名打开的。大家也可以通过搜索网创有方&#xff0c;或者直接点击网创有方 查看悬挂备案号后的效果。 首先大家可以看…

安全测试扫描利器-Burpsuite

&#x1f525; 交流讨论&#xff1a;欢迎加入我们一起学习&#xff01; &#x1f525; 资源分享&#xff1a;耗时200小时精选的「软件测试」资料包 &#x1f525; 教程推荐&#xff1a;火遍全网的《软件测试》教程 &#x1f4e2;欢迎点赞 &#x1f44d; 收藏 ⭐留言 &#x1…

vscode常用插件及插件安装方式

一、常用插件 Chinese (Simplified) (简体中文) Language Pack for Visual Studio Code 说明&#xff1a;中文语言包扩展&#xff08;简体&#xff09; open in browser 说明&#xff1a;可以在默认浏览器或应用程序中打开当前文件 Auto Rename Tag 说明&#xff1a;自动重…

Android 控件保持宽高比得几种方式

文章目录 Android 控件保持宽高比得几种方式adjustViewBounds百分比布局ConstraintLayout自定义View Android 控件保持宽高比得几种方式 adjustViewBounds 仅适用于 ImageView&#xff0c;保持横竖比。 <ImageViewandroid:layout_width"match_parent"android:l…

动态规划(Dynamic-Programming)问题讲解

动态规划类问题 从已知子问题的解&#xff0c;推导出当前问题的解 推导过程可以表达为一个数学公式用一维或二维数组来保存之前的计算结果&#xff08;可以进一步降维优化&#xff09; 将当前问题 分解成子问题 &#xff0c;找出递归公式&#xff0c;分阶段进行求解 求解过程中…

进程间通信(27000字超详解)

&#x1f30e;进程间通信 文章目录&#xff1a; 进程间通信 进程间通信简介       进程间通信目的       初识进程间通信       进程间通信的分类 匿名管道通信       认识管道       匿名管道       匿名管道测试       管道的四种…

第十五课,海龟画图:抬笔与落笔函数、画曲线函数

一&#xff0c;turtle.penup()和turtle.pendown()&#xff1a;抬起与落下画笔函数 当使用上节课学习的这个turtle.forward()&#xff1a;画笔前进函数时&#xff0c;画笔会朝着当前方向在画布上留下一条指定&#xff08;像素&#xff09;长度的直线&#xff0c;但你可能发现&a…

C++|set、map模拟实现<——红黑树

目录 一、红黑树的迭代器 1.1红黑树迭代器框架 1.2operator*() && operator->() 1.3operator() 1.4operator--() 1.5operator() && operator!() 1.6begin() && end() 二、如何用红黑树搭配map和set(仿函数) 三、红黑树封装map和set(简易版…

springboot + Vue前后端项目(第十三记)

项目实战第十三记 写在前面1.建立角色表2. 后端代码生成2.1 RoleController 3. 前端页面的搭建3.1 Role.vue3.2 路由3.3 Aside.vue3.4 页面效果 4.建立菜单表5.后端代码编写5.1 Menu5.2 MenuController 6.前端页面的搭建6.1 Menu.vue6.2 路由6.3 Aside.vue6.4 页面效果 总结写在…

keepalived安装文档

目录 1、安装环境 2、安装keepalived 2.1 上传keepalived安装文件 2.2 解压 2.3 安装keepalived 2.4 加入开机启动&#xff1a; 2.5 配置日志文件 2.6 打开防火墙的通讯地址 1、安装环境 su - root yum -y install kernel-devel* yum -y install openssl-* yum -y …

vx小程序初学

小程序初学 在我还没接触到微信小程序之前&#xff0c;通常使用轮播要么手写或使用swiper插件去实现&#xff0c;当我接触到微信小程序之后&#xff0c;我看到了微信小程序的强大之处&#xff0c;让我为大家介绍一下吧&#xff01; swiper与swiper-item一起使用可以做轮播图 …

把自己的服务器添加到presearch节点

Presearch is a scam. Before, judging by the price of the token you should have been able to get between $150-$200 after 12-13 months of regular searches. "If you use this service for the next 11 years you will have earned $30!" Presearch大约需要…

Easy RoCE:在SONiC交换机上一键启用无损以太网

RDMA&#xff08;远程直接内存访问&#xff09;技术是一种绕过 CPU 或操作系统&#xff0c;在计算机之间直接传输内存数据的技术。它释放了内存带宽和 CPU&#xff0c;使节点之间的通信具有更低的延迟和更高的吞吐量。目前&#xff0c;RDMA 技术已广泛应用于高性能计算、人工智…

车流量监控系统

1.项目介绍 本文档是对于“车流量检测平台”的应用技术进行汇总&#xff0c;适用于此系统所有开发&#xff0c;测试以及使用人员&#xff0c;其中包括设计背景&#xff0c;应用场景&#xff0c;系统架构&#xff0c;技术分析&#xff0c;系统调度&#xff0c;环境依赖&#xf…

MongoDB~存储引擎了解

存储引擎 存储引擎是一个数据库的核心&#xff0c;主要负责内存、磁盘里数据的管理和维护。 MongoBD的优势&#xff0c;在于其数据模型定义的灵活性、以及可拓展性。但不要忽略&#xff0c;其存储引擎也是插件式的存在&#xff0c;支持不同类型的存储引擎&#xff0c;使用不同…

导线防碰撞警示灯:高压线路安全保障

导线防碰撞警示灯&#xff1a;高压线路安全保障 在广袤的大地上&#xff0c;高压线路如同血脉般纵横交错&#xff0c;然而&#xff0c;在这看似平静的电力输送背后&#xff0c;却隐藏着不容忽视的安全隐患。特别是在那些输电线路跨越道路、施工等区域的路段&#xff0c;线下超…

顶点着色技术在AI去衣中的作用

在当今的数字时代&#xff0c;人工智能&#xff08;AI&#xff09;已经渗透到我们生活的方方面面&#xff0c;从智能家居到自动驾驶汽车&#xff0c;再到在线购物推荐。然而&#xff0c;AI的影响远不止于此。近年来&#xff0c;AI在图像处理和计算机视觉领域的应用取得了显著进…

【Python系列】Python 中方法定义与方法调用详解

&#x1f49d;&#x1f49d;&#x1f49d;欢迎来到我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 推荐:kwan 的首页,持续学…