Java中的String类
提示:本文主要讲述了Java中对String类的了解认识与学习。
一、String的常用方法
1) 字符串的三种构造方法
注意:由字符串的第二种构造方法可以知道String是一个引用类型,内部本身并不存储字符串。
字符串的三种构造方法
1.直接构造
String s1 = "hello";
2.使用关键字new对象构造,String是一个引用类型变量
String s2 = new String("world");
3.使用字符数组构造字符数组
char[] array1 = new char[]{'s','h','a','n','g','d','i'};
String s3 = new String(array1);
String s4 = s1;
System.out.println(s4);此时输出结果和s1是一样的
System.out.println(s1);
System.out.println(s2);
for each循环遍历array1数组
for (char x: array1) {
System.out.print(x);
}
System.out.println();
System.out.println(s1.length());//输出字符串长度
System.out.println(s1.isEmpty());//判断字符串是否为空
注意:1.String类型是一个引用类型变量s4内存储了s1这个引用指向对象的地址。
2.for each循环用来遍历数组 for each语法
( 数组元素类型 数组变量 :数组名)
2) 方法:输出字符串长度、判断字符串是否为空
3.字符串名.length()可以输出字符串的长度
数组名.length可以输出一个数组的长度,注意此时不要加()
4.字符串名.isEmpty()判断字符串是否为空,返回值类型为boolean,返回true或者false。
3) 字符串的比较
比较地址
String s1 = "hello";
String s2 = "world";
String s3 = "hello";
String s4 = s1;
System.out.println(s1 == s2);//false
System.out.println(s1 == s3);//false
System.out.println(s4 == s1);//true
此时比较的是在堆上的地址,String是一个引用类型,每new一次就会在栈上新开辟一块空间,在堆上存储新开辟空间的地址,因此前两个输出的为false,最后一个s4和s1存储了相同地址,指向了栈上的同一个对象,所以此时输出的是true。
equals方法和compareTo方法比较对象
String s1 = "hello";
String s2 = "world";
String s3 = "hello";
System.out.println(s1.equals(s2));
System.out.println(s1.equals(s3));
输出结果:
String s1 = "abc";
String s2 = "ab";
String s3 = "abcdef";
String s4 = "abc";
String s5 = "ef";
String s6 = "b";
System.out.println(s1.compareTo(s2));//输出1
前k个字符全部相等,则返回两个字符串的长度差s1比s2长度大1
System.out.println(s1.compareTo(s3));//输出-3
前k个字符串相等,s1比s3字符串长度大-3
System.out.println(s1.compareTo(s4));//输出0
两个字符串完全相同,返回数组0
System.out.println(s1.compareTo(s5));//输出-4
按照字典序比较,出现不同数字,则返回两个字符之差a和e之间差4 -4!!!
System.out.println(s5.compareTo(s6));//输出3
s5的第一个跟s6不相同,且e比b大3,所以返回数值3
}
输出结果:
总结
1.字符串==是比较两个字符串的地址是否相等,equals和compareTo方法是比较指向对象的内容大小是否相等。
2.equals方法的返回值类型是boolean,判断字符串内容是否相同compareTo方法返回值类型是int类型,判断字符串长度大小
3.compareTo方法,如果两个字符串完全相同则返回0,如果前k个字符相同,则返回字符串长度之差。
4.compareTo方法按字典次序比较,如果出现不同,则直接返回第一个字母的ASCII的值减第二个字母ASCII的值
5.语法规则 字符串s1 字符串s2
s1.equals(s2) s1.compareTo(s2)
另外在比较是否字符串中是否相同时候 String类中还提供了忽略大小写的方法。
public static void main(String[] args) {
/**
* String类里面的compareToIgnoreCase方法在字符串比较的时候忽略字符的大小写
*/
String s1 = "Abc";
String s2 = "abc";
String s3 = "ab";
System.out.println(s1.compareToIgnoreCase(s2));
System.out.println(s1.compareToIgnoreCase(s3));
}
输出结果:
4) 字符串的查找方法
charAt()方法
获取字符串某个位置的字符
String s1 = "hello";
System.out.println(s1.charAt(0));输出h
for (int i = 0; i < s1.length(); i++) {
System.out.print(s1.charAt(i));
遍历字符串 通过for循环逐个获取每个位置的元素并输出
}
indexOf方法和LastIndexOf方法
indexOf有很多重载的方法,可以从原字符串中找某个字符,从第i个位置找某个字符,从原字符串中找部分字符串片段,从某个位置开始找字符串片段,lastIndexOf方法同理,只是从后往前找,同样有许多重载的方法。如果没有找到则返回-1.
如下图所示:
5) 字符串类型转换
字符串转化为其他类型
public static void main(String[] args) {
其他类型转化为字符串,此时需要用到Sring类里面valueOf方法
valueOf有很多对应的重载方法,根据需求对应选择
String s1 = String.valueOf(123);
String s2 = String.valueOf(3.1415926);
String s3 = String.valueOf(true);
System.out.println(s1);
System.out.println(s2);
System.out.println(s3);
System.out.println("============");
字符串转化为其他类型,此时需要用到基本数据类型的包装类里面的方
法包装类.parsexxxx方法
String s4 = "123";
String s5 = "3.14";
String s6 = "true";
int a = Integer.parseInt(s4);
double d = Double.parseDouble(s5);
boolean b = Boolean.parseBoolean(s6);
System.out.println(s4);
System.out.println(s5);
System.out.println(s6);
}
输出结果:
这里可以体现八大基本数据类型所对应的包装类的作用,可以调用包装类里面的方法,进行数据类型的转化。
字符串大小写的转换toUperCase() / toLowerCase()
字符串与数组之间的转化
格式化输出
需要注意的是格式化输出的是方法是一个静态方法,需要调用类名.方法实现调用。
6) 字符串的替换与拆分
repalceAll方法和replaceFirst方法
public static void main(String[] args) {
String s = "hello123123";
System.out.println(s.replaceAll("123","world"));
System.out.println(s.replaceFirst("123","world"));
}
输出结果:
split方法
String str = "hello how are you";
split有两个重载的方法
1.分别是按照xxx将字符串全部拆分
2.按照xx将字符串拆分为多少段,部分拆分。
String[] result = str.split(" ");
for ( String x : result) {
System.out.println(x);
}
String[] result2 = str.split(" ", 3);
for ( String y : result2) {
System.out.println(y);
按照空格将字符串拆分为三个字符串
所以输出结果是
hello
how
are you
输出结果:
多个字符与特殊字符的拆分
输出结果:
由此处我们可以看出在按照多个字符串拆分时候,先按照一种字符串对应拆分好后放入新的字符串数组中去,然后再按照另一个字符串对这个数组中每个下标元素进行拆分,示例可以表现为result[i].split.
注意
1.如果字符串为 | * + . 都必须加上转义字符\
2.如果是按照\分割字符串串,就需要用\\
3.如果一个字符串有多个分割符可以用|作为连字符使用
上述代码可以做如下改进
7) 字符串的截取
字符串的截取用到了String类里面的subString方法。有两种重载方法
1.从某个位置开始截取一直到末尾。
2.从某个位置截取到某个位置,特别注意左闭右开
8) 字符串的其他使用方法
trim方法
去掉字符串两边的空格,保留中间的空格
二、字符串的不可变性与修改
1) 不可变性
观察String类的源码,类被final修饰,成员变量中的字符数组被final修饰。
如何在堆和栈上理解String类的不可变性
深层理解字符串的不可变性
1.字符串不可变不是因为其内部的字符数组被final修饰了因此不可变,也不是因为类被final所修饰
2.类被final修饰表面该类不想被继承,被final修饰的引用变量不能指向其他的对象,但是指向对象中的内容是可以发生改变的
2) 不可变对象的好处
1.方便实现字符串对象池,如果String类改为可变的,那么在拷贝时候就需要考虑深浅拷贝的问题。
2.不可变对象在进行多线程编程时候是安全的
3.不可变对象更加方便缓存。
3) 字符串的修改
字符串的修改实际上创建了一个新的对象,这个时候浪费资源,占用时间,效率十分慢引入了StringBuilder和StringBuffer来对字符串进行修改,避免了创建许多临时对象。以String类中replace方法源码举例,可以看出又创建了一个新的对象。
三、StringBuilder和StringBuffer
1) String和StringBuilder的转换
1.String类转化为StringBulider时候调用他的构造方法或者append方法
2.StringBuilder转化为String类的时候调用StringBuilder里面的toString方法。
2) String、StringBuidler、StringBuffer的区别
1.String的内容是不可修改的,StringBuilder和StringBuffer的内容是可以被修改的。
2.StringBuilder和StringBuffer的功能大多是相似的
3.StringBuffer属于采用同步处理,属于线程安全操作,StringBuilder未采用同步处理,属于线程不安全操作。
在不考虑常量池存在的前提下,下面分别创建了多少个对象
String str1 = new String("ab");
String str2 = new String("a") + new String("b");
3) 常量池
1.凡是用引号引起来的都是统一放到常量池中的。
2.如果常量池有那就不再额外进行存储。如果常量池中没有就需要在常量池中申请一块空间用来存放。
解答