String 类的详解
1.字符串的构造
String 类提供的构造方式非常多,常用的为以下三种:
例1:创建一个字符串
public class TestDemo {
public static void main(String[] args) {
//1.使用常量串构造
String str1="hello java!";
System.out.println(str1);
//2.直接new String对象
String str2=new String("hello java!");
System.out.println(str2);
//3.使用字符数组进行构造
char[] chars={'h','e','l','l','o',' ','j','a','v','a','!'};
String str3=new String(chars);
System.out.println(str3);
}
}
其运行结果:
【注意】:1.String 是引用类型,内部并不存储字符串本身,String类型是包含了两个属性,一个是char类型的数组value,一个是int类型的hash。
例2:关于字符串的存储(画图解释)
public class TestDemo {
public static void main(String[] args) {
String str1=new String("hello");
String str2=new String("java");
}
}
图解大概内存简解:
2.字符串对象的比较
1.==比较是否引用同一个对象
例3: 用等号比较
public class TestDemo {
public static void main(String[] args) {
//对于基本类型的数据,==比较两个变量中存储的值是否相等
int a=10;
int b=20;
int c=10;
System.out.println(a==b);//false
System.out.println(a==c);//true
//对于引用类型的数据,==比较引用两个引用变量引用的是否为同一对象,比较的是地址
String str1=new String("hello");
String str2=new String("java");
String str3=new String("java");
String str4=str3;
System.out.println(str1==str2);//false
System.out.println(str2==str3);//false
System.out.println(str3==str4);//true
}
}
其运行结果:
【注意】:对于内置类型,等号比较的是变量中的值;对于引用类型,等号比较的是引用中的地址。
2.boolean equals(Object anObject) 方法:按照字典序比较,对象的内容是否相同,返回值为boolean
例4:equals比较
public class TestDemo {
public static void main(String[] args) {
String str1=new String("Java");
String str2=new String("java");
String str3=new String("java");
// str1、str2、str3引用的是三个不同对象,因此==比较结果全部为false
System.out.println(str1==str2);//false
System.out.println(str2==str3);//false
System.out.println(str1.equals(str2));//false
System.out.println(str2.equals(str3));//true
//忽略大小写比较对象的内容是否相同
System.out.println(str1.equalsIgnoreCase(str3));//true,
}
}
其运行结果:
【注意】 :equals比较的是对String对象中的逐个字符比较。
3.compareTo(String s) 方法: 按照字典序进行比较,返回值为int
与equals不同的是,equals返回的是boolean类型,而compareTo返回的是int类型。具体比较方式:
1.先按照字典次序大小比较,如果出现不等的字符,直接返回这两个字符的大小差值。
2.如果前k个字符相等(k为两个字符长度最小值),返回值两个字符串长度差值。
例5:compareTo比较
public class TestDemo {
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");
String s5=new String("ABc");
System.out.println(s1.compareTo(s2));//不同输出字符差值为-1
System.out.println(s1.compareTo(s3));//相同输出为0
System.out.println(s1.compareTo(s4));//前k个字符完全相同,输出长度差值为-3
//忽略大小写的比较,比较方式和上面一样
System.out.println(s1.compareToIgnoreCase(s5));//忽略大小写,完全相同输出为0
}
}
其运行结果:
3.字符串查找
【注意】:上述方法都是实例方法。
4.字符串的相关操作函数
4.1数值和字符串的转化
例6:数值和字符串相互转化
class Student {
String name;
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 TestDemo extends Student{
public TestDemo(String name, int age) {
super(name, age);
}
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("张三",18));
System.out.println(s1);
System.out.println(s2);
System.out.println(s3);
System.out.println(s4);
System.out.println("===========================")
//字符串转数字
int data1=Integer.parseInt("1234");
double data2=Double.parseDouble("12.34");
boolean data3=Boolean.parseBoolean("true");
System.out.println(data1);
System.out.println(data2);
System.out.println(data3);
}
}
其运行结果:
4.2字符串的大小写转化
例7:大小写转化
public class TestDemo {
public static void main(String[] args) {
String s1="hello";
String s2="HELLO";
//小写转大写
System.out.println(s1.toUpperCase());
//大写转小写
System.out.println(s2.toLowerCase());
}
}
其运行结果:
**【注意】:**只是对字母转化起作用,对文字没有用;
4.3字符串和数组的相互转化
例8:字符串和数组的转化
public class TestDemo {
public static void main(String[] args) {
//字符串转数组
String s="hello";
char[] chars=s.toCharArray();
for(char x:chars){
System.out.print(x+" ");
}
System.out.println();
//数组转字符串
String s1=new String(chars);
System.out.println(s1);
}
}
其运行结果:
4.4字符串的格式化
例9:格式化
public class TestDemo {
public static void main(String[] args) {
String s=String.format("%d-%d-%d",2022,6,29);
System.out.println(s);
}
}
其运行结果:
4.5字符串的替换
使用一个指定的新字符串替换已有的字符串的数据。可用下列方法:
例10:字符串的替换处理
public class TestDemo {
public static void main(String[] args) {
String str="hellojava!";
System.out.println(str.replaceAll("a","b"));
System.out.println(str.replaceFirst("l","b"));
System.out.println(str);
}
}
其运行结果:
**
【注意】: 由于字符串是不可变对象, 替换不修改当前字符串, 而是产生一个新的字符串。
4.6字符串拆分
可以将一个完整的字符串按照指定的分隔符划分为若干个子字符串。可用方法如下:
例11:字符串的拆分
public class TestDemo {
public static void main(String[] args) {
String str="hello java hello world";
String[] strings=str.split(" ");//分隔符为空格
for(String x:strings){
System.out.println(x);
}
}
}
其运行结果:
例12:字符串的部分拆分
public class TestDemo {
public static void main(String[] args) {
**加粗样式** String str="hello java hello world";
String[] strings=str.split(" ",3);//分隔符为空格,拆分成3组
for(String x:strings){
System.out.println(x);
}
}
}
其运行结果:
拆分是特别常用的操作。一定要重点掌握,另外有些特殊的分隔符需要转义才行。
1.字符" | “,” * “,” + “,” . " 都需要在前面加上转义字符" \ “;
2.如果是” \ “,则是要写成” \\ “;
3.如果是一个字符串有多个分隔符,可以用” | "作为连字符;
例13:分割符为" | "
public class TestDemo {
public static void main(String[] args) {
String str="192|168|11";
String [] strings=str.split("\\|");
for(String x:strings){
System.out.println(x);
}
}
}
其运行结果:
例14:多次拆分
public class TestDemo {
public static void main(String[] args) {
String str="name=zhangsan&age=18";
String [] strings=str.split("&");
for (String x:strings) {
String [] strings1=x.split("=");
for (String y:strings1){
System.out.println(y);
}
}
}
}
其运行结果:
4.7字符串截取
从一个完整的字符串中截取出部分内容。可用方法如下:
例15:截取的实现
public class TestDemo {
public static void main(String[] args) {
String str="helloworld";
System.out.println(str.substring(5));//截取从下标为5开始到结尾下标的内容
System.out.println(str.substring(0,5));//截取从0下标到4下标的内容
}
}
其运行结果:
【注意】
1.索引从0开始;
2.注意区间为前闭后开,[0,5);
4.8去掉字符串左右两边的空格
例16:trim()的实现
public class TestDemo {
public static void main(String[] args) {
String str=" hello world! ";
System.out.println("["+str+"]");
System.out.println("["+str.trim()+"]");
}
}
其运行结果:
5.字符串常量池
在Java程序中,类似1,2,3.14,"hello"等字面常量频繁使用,为了使程序的运行速度更快,更节省内存,Java为8中基本数据类型和String 类型提供了常量池。
为了节省空间以及程序的运行效率,Java引入了:
1.Class文件常量池: 每个.Java源文件编译后生成.Class文件中会保存当前类中的字面常量以及符号信息
2.运行时常量池:在.Class文件被加载时,.Class文件中的常量池被加载到内存中称为运行时常量池,运行时常量池每个类都有一份。
3.字符串常量池。
字符串常量池: 在JVM中是String Table类,实际上是一个固定大小的Hash Table(一种高效用来进行查找的数据结构),Java8后,字符串常量池在堆中。
5.1再谈String 对象的创建
例17:画图解释下面的代码在内存中的体现
public class TestDemo {
public static void main(String[] args) {
String str1="hello";
String str2="hello";
String str3=new String("hello");
String str4=new String(new char[]{'j','a','v','a'});
String str5="java";
System.out.println(str1);
System.out.println(str2);
System.out.println(str3);
System.out.println(str4);
System.out.println(str5);
}
}
代码在内存中的体现:
6.字符串的不可变性
String是一种不可变对象,字符串中的内容是不可改变的,字符串不可修改,是因为:
String类在设计的时候就是不可改变的,String类实现描述中已经说明了。
1.String类被final修饰说明,该类不能被继承。
2.String类中的属性value [ ]是被private final修饰:
value被修饰被final修饰,表明value自身的值不能改变,即不能引用其它字符数组,但是其引用空间中
的内容可以修改。而归根到底,不能被改变,是因为private修饰,类外部不能引用value。
注意: final修饰类表明该类不想被继承,final修饰引用类型表明该引用变量不能引用其他对象,但是其引用对象中的内容是可以修改的。
7.字符串的修改
7.1直接拼接修改
注意:尽量避免直接对String类型对象进行修改,因为String类是不能修改的,所有的修改都会创建新对象,效率非常低下。
例18:低效率的字符串拼接
public static void main(String[] args) {
String s = "hello";
s += " world";
System.out.println(s); // 输出:hello world
}
这种方式不推荐使用,因为其效率非常低,中间创建了好多临时对象。因为每一次拼接都会创建一个对象。
7.2借助StringBuffer 和 StringBuilder
这两者大部分功能是相同的,介绍一些StringBuilder的常用方法
注意:String和StringBuilder最大的区别在于String的内容无法修改,而StringBuilder的内容可
以修改。频繁修改字符串的情况考虑使用StringBuilder。相当于原先的内容被改变了。
String、StringBuffer、StringBuilder的区别:
- String的内容不可修改,StringBuffer与StringBuilder的内容可以修改。
- StringBuffer与StringBuilder大部分功能是相似的。
- StringBuffer采用同步处理,属于线程安全操作;而StringBuilder未采用同步处理,属于线程不安全操
作。