文章目录
前言
一 String类
1. String类简介:
在c语言中字符串用字符数组来存储,并没有专门的字符串类型。
在java中,专门针对字符串创建了一个String类.
String对象的字符串不能被修改
String对象中存储的字符串是不能被修改的,是因为存储字符串的数组被private修饰!
只能在本类中被访问修改!而不能在其他类中被访问修改。
这是jdk17的数组,在jdk1.8中数组类型为:char[]
对于String对象中字符串不能被修改的原因,有些网上评论误解为是final关键字修饰导致的。
对于修饰String类的final关键字:
此final关键字的作用是设置String类不能够被继承!
对于修饰存储字符串数组的final关键字:
此final关键字的作用是让value引用的值不能够改变,即不能引用别的对象。但是所引用的对象中的内容是可以被改变的! 所以这并不是String对象中的字符串不能被修改的原因!
举例:
2.字符串的三种构造方法:
//常量字符串
String string1 = "hello world";
//通过实例化String对象
String string2 = new String("hello world");
//通过字符数组
char[] arr1 = {'a','b','c','d','e','f'};
String string3 = new String(arr1);
System.out.println(string1);
System.out.println(string2);
System.out.println(string3);
字符串在内存中的存储:
字符串本身并不存储在String对象中,String对象所存储是存储字符串的数组的地址。
在String类中,不只是只有value与hash属性:
所以上面的图省略了类中一些其他的属性,如图所示,在对象中存放着value引用的值,value指向的数组则并不存储在对象中!
3. 字符串的比较:
字符串的比较有四种方式:== , equals方法, compareTo方法,compareToIgnoreCase方法
关系运算符 ==:
//此关系运算符只能比较基本数据类型的值,不能比较引用数据类型指向的对象的值,可以比较引用数据类型的引用的地址是否相等
String string1 = new String("hello world");
String string2 = new String("hello world");
System.out.println(string1==string2); //只是比较了两个引用中的地址。
equals方法:
//通过调用equals方法可以判断,两个字符串是否相等
String string1 = new String("hello world");
String string2 = new String("hello world");
String string3 = new String("haha");
System.out.println(string1.equals(string2)); //相等
System.out.println(string1.equals(string3)); //不等
System.out.println(string2.equals(string3)); //不等
compareTo方法:
调用compareTo方法,比较哪个字符串大,哪个字符串小!(String类实现了comparable接口)
与equals方法返回boolean值不同,compareTo方法返回int类型:
具体的比较方式:
1 先按照字典次序大小比较,如果出现不等的字符,直接返回这两个字符的大小差值。
2 如果前k个字符相等(k为两个字符长度最小值),返回值两个字符串长度差值。
String string1 = new String("hello world");
String string2 = new String("hello world");
String string3 = new String("haha");
System.out.println(string1.compareTo(string2));
System.out.println(string2.compareTo(string3));
System.out.println(string1.compareTo(string3));
//0表示两个字符串相等,正数表示调用方法的字符串比输入的实参字符串大,负数表示小!
compareToIgnoreCase方法:
调用 compareToIgnoreCase方法,忽视字符串大小写的差异进行比较。
String string1 = "Hello world";
String string2 = "hello world";
System.out.println(string1.compareTo(string2)); //对比两个方法比较的异同
System.out.println(string1.compareToIgnoreCase(string2));
4.字符串的查找
正序查找:
- charAt方法:——查找指定的下标的字符:
String string1 = "my name is zhang"; //空格也算一个字符
for (int i = 0; i < string1.length(); i++) {
char ch = string1.charAt(i);
System.out.print(ch);
}
2. indexof方法——查找指定的字符的下标
在字符串中找指定字符的下标:
//如果有该字符返回下标值,没有返回-1
String string2 = "hello bit";
System.out.println(string2.indexOf('e'));//找到了下标为1
System.out.println(string2.indexOf('w'));//未找到-1
//从指定位置开始顺序查找:
System.out.println(string2.indexOf('e',2));//从下标2开始查找
- indexof方法:——查找指定字符串的下标
String string3 = "hello bit";
System.out.println(string3.indexOf("ll")); //第一个'I'的下标为2
//在字符串中指定位置开始顺序查找指定字符串
System.out.println(string3.indexOf("ll",2));
逆序查找:
lastIndexof方法——逆序查找字符与字符串
//1.1 从后往前查找字符
String name = "zhangsan";
System.out.println(name.lastIndexOf('g'));//下标不会变,只是改变查找的顺序方向!
//1.2 从指定位置开始逆序查找字符
String name = "zhangsan";
System.out.println(name.lastIndexOf('g',1)); //从下标1开始逆序寻找
//2. 逆序查找字符串
// 1.1 逆序查找字符串,默认从字符串最后的位置开始
//在查找字符串时,从指定的位置开始往后判断是否有指定的字符串,没有再往前查找
//也就是说,逆序查找字符串时,本质上是字符串首字符的逆序
String name = "zhangsan";
System.out.println(name.lastIndexOf("an"));
//1.2 从指定位置开始逆序查找字符串
String name = "zhangsan";
System.out.println(name.lastIndexOf("an"));
5 字符串的转化:
5.1 valueof方法: 数字转化成字符串
String string1 = String.valueOf(1234);//valueof是静态方法!
System.out.println(string1+1); //字符串连接
//字符串转化成数字——整型Interger
int i1 = Integer.parseInt(string1); //调用Integer类中的parseInt方法
System.out.println(i1+1); //+1后的值是1235,说明成功转化成数值
5.2 valueof方法,对象转化成字符串
class Student{
private String name;
private int age;
public Student(String name, int age) {
this.name = name;
this.age = age;
}
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
public class Test {
public static void main(String[] args) {
String string2 = String.valueOf(new Student("张三",10)) ;
System.out.println(string2);
}
}
5.3 字符串大小写相互转换:
前面我们讲过,String对象中字符串是不能被修改的,转换的本质是新创建了一个对象。
//字符串大写转换成小写方法:
//字符串小写转换成大写方法:
//大写转换成小写
String string1 = "Hello world";
System.out.println(string1.toLowerCase());
//小写转换成大写
String string2 = "hello world";
System.out.println(string2.toUpperCase());
5.4 字符串与数组之间相互转换:
//字符串转换成数组!
String string3 = "hello world";
for (int i = 0; i < string3.length(); i++) {
char ch = string3.charAt(i);//charAt
}
System.out.print(ch+" ");
System.out.println();
//数组转换成字符串
char [] chars = {'a','b','c','d','e'};
String string4 = new String(chars);
System.out.println(string4);
5.5 格式化format方法——是将数据以格式化的形式变为字符串
String string5 = String.format("%d_%d_%d",2019,10,05);
System.out.println(string5);
6 字符串的替换:
前面我们讲过,String对象中字符串是不能被修改的,替换的本质是新创建了一个对象。
//字符串替换:——替换字符,替换字符串
如图:即是所有的replace重载的方法,
第一个方法用于替换字符
其他三个方法用于替换字符串
在替换字符串的方法中,replace与replaceAll方法作用相同,是替换字符串中所有的指定字符串。
replaceFirst方法只替换字符串中第一个出现的指定字符串。
//字符串替换:——替换字符,替换字符串
String string1 = "hello world";
//将所有的l字符转换成L字符
System.out.println(string1.replace('l','L'));
//替换hello字符串
System.out.println(string1.replace("hello","my"));
//replaceAll与替换字符串replace的功能相同
System.out.println(string1.replaceAll("hello","my"));
//替换第一个出现的指定字符串
System.out.println(string1.replaceFirst("l","L"));
7. 字符串的拆分 — split方法 :
前面我们讲过,String对象中字符串是不能被修改的,拆分的本质是新创建了数个String对象存储’‘分割’'后的字符串。
如图,第一个方法按照指定的字符串将字符串全部拆分
第二个方法限制了拆分的组数。
String string1 = "hello wor ld";
//以某一个字符为界限,拆分字符串成多个字符串,字符以字符串的形式作为参数!
String []strings = string1.split(" ");
for (int i = 0; i < strings.length; i++) {
System.out.println(strings[i]);
}
//对字符串拆成几部分做出限制!
String[] strings1= string1.split(" ",2);
for (int i = 0; i < strings1.length; i++) {
System.out.println(strings1[i]);
}
特殊情况:对于正则表达式的拆分:
//1. 字符"|","*","+"都得加上转义字符,前面加上 "\\"
// 2. 而如果是 "\",那么就得写成 "\\\\" ."
// "3. 如果一个字符串中有多个分隔符,可以用"|"作为连字符.
String string2 = "hello+world"; //
String []strings = string2.split("\\+");
for (int i = 0; i < strings.length; i++) {
System.out.println(strings[i]);
}
String string3 = "hello\\wo rld";
String []strings1 = string3.split("\\\\| ");
for (int j = 0; j < strings1.length; j++) {
System.out.println(strings1[j]);
}
8. 字符串的截取:
前面我们讲过,String对象中字符串是不能被修改的,字符串的截取本质上是新创建一个对象。
//从指定位置开始一直截取到头:
String string1 = "hello world";
System.out.println(string1.substring(2)); //从下标2开始截取!
//从指定位置开始截取,再指定位置结束:
System.out.println(string1.substring(1,6)); //从下标1开始截取,截取到下标6,下标6'w'是不截取的
//java中的规则一般是前闭后开 [ )
另外一个方法:
//另外一个去除字符串两边空格的方法
String s1 = " hehe ";
System.out.println("["+s1+"]");
System.out.println("["+s1.trim()+"]"); //去除了字符串两侧的空格!!!
总结(重要):
1 . String类中方法,凡是涉及到修改字符串的,均是生成了一个新的字符串!
2. String类中还有其他方法,这里不一一列举,我们不应该硬背这些方法,而是在需要时,去帮助手册,或者官网上查阅。
二 StringBuffer类
2.1 StringBuffer类的声明:
StringBuffer类可以看作是一个特殊的String类,特殊在StringBuffer类的字符串可以被修改。
此时的value数组并没有被private修饰,数组其访问权限增大,可以在外面的类中被修改。
2.2 字符串的插入—insert方法
在指定下标插入字符串
StringBuffer stringBuffer = new StringBuffer("hello world");
System.out.println(stringBuffer.insert(2, "比特"));
System.out.println(stringBuffer); //从结果中可以看到stringBuffer被修改
结果说明,原字符串真的被修改了。
2.3 StringBuffer类型转变成String类型:
通过toString方法,即可发生类型转变!
转变为String类型!
三 StringBuilder类
- 对于StringBuilder类中的字符串的修改也是在原字符串上进行的
- StringBuilder类与StringBuffer类功能方法,大体相同。
StringBuilder类与StringBuffer类的区别:
StringBuilder类用于单线程
StringBuffer类 用于多线程
举例:
这是StringBuffer类中的toString方法:
这是StringBuilder类中的toString方法:
分析: 我们不分析代码的具体实现,两者的差别在于一个有StringBuffer类前有一个synchronized关键字修饰。
首先,多线程与单线程调用资源就好似一群人使用公共资源与一个人使用资源。
多线程中只能一个线程一个线程地调用资源,当一个线程使用资源时,其它线程就不能使用,怎么保证?需要一把锁!,而synchronized就相当于这把锁!
这个关键字我们以后会讲到,这里不再阐述!