前言: 我们知道 String 其实就是字符串的引用类型。在C语言中已经涉及到字符串了,但是在C语言中要表示字符串只能使用字符数组或者字符指针,可以使用标准库提供的字符串系列函数完成大部分操作,但是这种将数据和操作数据方法分离开的方式不符合面向对象的思想,而字符串应用又非常广泛,因此Java语言专门提供了String类。
提醒:本文章讲到的方法会比较多,但绝大多数都简单。
1.各种基本方法
第一种和第二种没有什么区别,第三种是先定义一个字符数组 char,然后再用 new String 把它改为字符串。常用的就这以上三种。
虽然在 “” 中未提到 String,但它也是 String 类型的对象,而且顺带一提,可以利用
“字符串”.length()来让编译器直接打印字符串的长度,非常方便,这个在后面也会被用到。
先来看下面一组例子:
在第一张图中,关于 == 和 .equals() ,虽然在本例子中得到的结果一样;但是这两种方法有本质上的区别。
== 它的内部实现是将两个对象的地址拿来比较,s1 和 s2 都是hello,然后令 s3 等于 s1(正确来说应该是s1赋值给s3),这时在编译器中 s3 和 s1 的地址就会是相同的,所以s1判断等于s3就会是正确的,然后由于s1和s2两个对象的地址都不一样,所以判断等于的布尔值就会是false。
但是 .euqals() 就不一样了,它是直接从对象的内容进行比较,这一点在第二张图中有所体现。同样是s1 和 s2 都是hello,然后令s1赋值给s3,这时s1、s2和s3的内容全部都会是一样的。所以布尔值全都是true。
下来是比较字符串大小的方法:
具体格式就是(以s1比上s2为例)s1.compareTo(s2),这种方式的执行流程是这样的:先从你两个对象的分别第一个字符进行比较,比较是根据该字符ASCII码值大小进行比较的,如果值是相同的,则再对两对象的第二个字符进行ASCII码值比较,全部相同则返回0;如果值是不同的,则会返回 第一个字符的ASCII码值减去第二个字符的ASCII码值,所以有可能是正数,也有可能是负数。具体可以看下图的举例:
还有可能两个对象的长度不同从而无法比较,这时编译器就会看长度来比较。
由于是s1比较s2,所以长了布尔值就是正数,反之就是负数。
下来是关于 compareToIgnoreCase 的用法,看下图的例子我想大家也能猜出来它是干啥的了:
没错,IgnoreCase 可以理解为忽略大小写,所以本题中 “F” 和 “f” 它们的ASCII码值是相同的。return 就会是0。
下来是charAt,它经常用于返回字符串中指定位置的字符,具体用法如下:
charAt(0),说明是指代该字符串的第一个字符,如果是2则是第三个字符,以此类推。若超出有效范围,则会编译报错。
我们还可以通过这个方法来遍历字符串:
接下来是 indexof ,可用来寻找字符串中的某个字符常量的首个下标(默认从0下标开始找):
还可以限定开始的范围,只需先加上逗号,再在逗号后面加上开始的下标即可:
下面是 lastIndexOf ,它用来查找某个元素最后出现的位置下标,搜索方向是从后往前查找:
同样还可以限定开始的范围,只需先加上逗号,再在逗号后面加上开始的下标即可(顺带一提,很多方法其实都可以限定范围):
以上就是用的比较多的方法,大概总结一下就如下图:
:
除上述的以外,还有一些其他的方法,也可能经常使用。
先是 toUpperCase ,它可用来将字符串中的小写字母变为大写字母,如下图:
与之相对的则是 toLowerCase ,用法自不用说,就是将大写字母变为小写字母,如图:
下来是 format,作用是将变量或值插入到字符串的指定位置,它们之间要使用%XXX,具体看你所用的类型,如图所示:
然后是 replace(a,b) ,作用是将 a 的值替换成 b 的值,如果不做说明则是全部替换,还可以替换一组值(不一定只能是一个),详见下图:
y
如果是限定了的呢?那就要先改变写法成 replaceFirst(指替换第一个下标或第一组的值) 或replaceAll(指将值全部进行替换)
然后是 split() ,作用是以括号内填的值为基准,分开两边的值,这时会至少有两个及以上的值,我们必须要用相应类型的数组来接收,否则会编译报错。还可以以两个值为基准,只需要在两值中间加上“|”即可【例:split(& |,)】
还有一些注意事项:
下来是字符串截取 substring ,作用如下:
然后是 trim ,他是用来去除字符串左右两边的空格的(只能去除):
2.转化
String 转换在Java中是一个常见操作,为什么要转化呢?原因如下:
- 数据类型匹配:不同系统或函数需要特定数据类型,例如数字计算需要数值类型而非字符串。
- 数据标准化:统一格式便于处理,如将用户输入的“123”转为整数123。
- 序列化与反序列化:网络传输或存储时,将对象转为字符串(如JSON),使用时再转换回来。
- 性能优化:某些场景下操作数值比操作字符串更高效。
如上图所示,虽然打印出来的还是相同的数字或字母,但是它们全都转化(修改)成了字符串,不再是原来的类型。
StringBuffer 和 StringBuilder
如果在累加,遍历或者一些用到循环的情况时,使用 “+=” 虽然可以解决问题,但是代码执行效率慢(循环)是不可避免的。所以我们引入StringBuffer 和 StringBuilder 来解决这个问题。
我们先来看这两种方法的相应解决方案,相信看了之后对于它的语法就能有所理解:
StringBuffer 和 StringBuilder 它们两个的源码分别如下,StringBuffer代表的是多线程,StringBuilder代表的是单线程,它们之间有什么区别呢?
多线程情况可以假设成你在公共厕所排队上厕所,你在上厕所时一定会锁门,然后后面的每个人都在排队等你上好厕所出来;你出来的时候,一定会先开锁开门才能出来,接下来下一个人也要先关门再锁上,才算是轮到下个人。就这样一直如此循环往复。
而单线程情况就可以比喻为只有你一个人在家,你去上厕所,这时候你锁不锁门其实已经没有意义了,这时如果你再锁门反而会变得更加麻烦。(即本来可以用单线程完成的问题如果用多线程去完成反而会本末倒置)。
然后就是本节String的例题了,一起来看一看:
问:输出的结果是多少?
答:B;可看下图:
答:B;==号两边的是引用数据类型,那么比较的是"地址相不相同"。"admin",存放在常量池当中,但是通过方法,userId.toLowerCase()。返回的是一个新的对象,大家可以看看该方法的源码。最终的返回值是:return new String(形参.....); 并不是常量池的"admin"。所以,这里比较的结果就是false。与上题还是有一点类似的。
参考代码:
注意:代码出现错误或异常时,要学会进行调试,这样自己才能找到代码的问题所在。
参考代码:
本篇文章到此结束。
本篇文章的截图和课件均摘自 比特科技 。希望能对你有帮助。