在C语言中要表示字符串只能使用字符数组或者字符指针,而且需要再使用标准库提供的字符串系列函数来完成大部分字符串相关的操作。但是这种将数据和操作数据的方法分开的方式不符合面向对象的思想,因此,Java专门提供了String类。
//使用常量串构造
String s1 = "hello";
//直接new String对象
String s2 = new String("hello");
//通过字符数组构造
char[] array = {'h','e','l','l','o'};
String s3 = new String(array);
注:
- String是引用类型,内部并不存储字符串本身。
- 在Java中,“” 引起来的也是String类型对象。
1. == 比较是否引用同一个对象
注:对于基本类型变量,比较的是两个变量中存储的值是否相同;
对于引用类型变量,比较的是两个引用变量引用的是否是同一个对象
int a = 10;
int b = 20;
int c = 10;
String s1 = new String("string1");
String s2 = new String("string2");
String s3 = s1;
// 比较基本数据类型
System.out.println(a==b); //false
System.out.println(a==c); //true
// 比较引用数据类型
System.out.println(s1==s2); //false
System.out.println(s1==s3); //true
2. boolean equals(Object o)
注:默认按照==比较 但是在自己重写之后可以按照自己定义的比较规则比较。
String s1 = new String("string1");
String s2 = new String("string2");
String s3 = s1;
System.out.println(s1.equals(s2)); //false
System.out.println(s1.equals(s3)); //true
3. int compareTo(String s)
注:1 先按照字典次序大小比较,如果出现不等的字符,直接返回这两个字符的大小的差值。
2 如果两个字符串的长度不一样,且前K个字符相同,返回两个字符串长度的差值
String s1 = new String("string1");
String s2 = new String("string2");
String s3 = s1;
System.out.println(s1.compareTo(s2)); //-1
System.out.println(s1.compareTo(s3)); //0
4. int compareToIgnoreCase(String s)
注: 和compareTo()比较方式一样,但是忽略大小写。
String s1 = new String("String1");
String s2 = new String("string2");
String s3 = s1;
System.out.println(s1.compareToIgnoreCase(s2)); //-1
System.out.println(s1.compareToIgnoreCase(s3)); //0
//得到字符串中位置为index的字符
char ch = s1.charAt(index);
//从前往后找 返回字符ch第一次出现的位置 没有返回-1
int index = s1.indexOf(char ch);
//从fromIndex开始往后找 找第一次出现字符ch的位置
int index = s1.indexOf(ch,fromIndex);
//从前往后找 返回字符串str 第一次出现的位置 没有返回-1
int index = s1.indexOf(String str);
//从fromIndex开始往后找 找第一次出现字符串str的位置
int index = s1.indexOf(String str,fromIndex);
//从后往前找 返回字符ch第一次出现的位置 没有返回-1
int index = s1.lastIndexOf(char ch);
//从fromIndex开始往前找 找第一次出现字符ch的位置
int index = s1.lastIndexOf(char ch,fromIndex);
//从后往前找 返回字符串str 第一次出现的位置 没有返回-1
int index = s1.lastIndexOf(String str);
//从fromIndex开始往前找 找第一次出现字符串str的位置
int index = s1.lastIndexOf(String str,fromIndex);
//数字转字符串
String s1 = String.valueOf(123);
String s2 = String.valueOf(123.12);
//字符串转数字
int data1 = Integer.parseInt("123");
double data2 = Double.parseDouble("123.12");
String s1 = "hello";
String s2 = "HELLO";
//小写转大写
String data1 = s1.toUpperCase();
//大写转小写
String data2 = s2.toLowerCase();
String s1 = "hello";
char[] arr = {'w','o','r','l','d'};
//字符串转数组
char[] chars = s1.toCharArray();
//数组转字符串
String str = new String(arr);
String s1 = String.format("%d-%d-%d",2000,10,1);
System.out.println(s1); //2000-10-1
String s1 = "hello";
//替换全部的单个字符或者替换全部的字符串
String str1 = s1.replace('l','a');
String str2 = s1.replace("he","ab");
//替换全部的字符串
String str3 = s1.replaceAll("ll","aa");
//替换第一个字符串
String str4 = s1.replaceFirst("he","ab");
String s1 = "hello world and people";
//按“ ”将s1拆分 将结果保留在String数组中
String[] ret1 = s1.split(" ");
//按“ ”将s1拆分 拆分成2组 第二组和之后的信息是一个整体不再拆分
String[] ret2 = s1.split(" ",2);
注:可以使用for-each语句进行多次拆分
String s1 = "hello";
//从1位置开始截取到结束
String str1 = s1.substring(1);
//截取1-3之间的部分 不包括3位置处 [1,3)
String str2 = s1.substring(1,3);
String s1 = " hello ";
//去掉字符串左右两侧的空格 保留中间的空格
String str = s1.trim();
String s1 = "hello";
String s2 = "hello";
String s3 = new String("hello");
String s4 = new String("hello");
System.out.println(s1==s2); //true
System.out.println(s3==s4); //false
为什么 s1和s2创建方式相同 s1==s2,但是s3和s4创建方式也相同 s3!=s4 ?
这就不得不提到常量池了: 类似于,1、3.14、“hello”等字面类型的常量经常频繁使用,Java为了使程序运行的速度更快、更节省内存;就引入了常量池,当这些字面常量第一次创建的时候,Java先把他们存储到常量池中,再赋予变量,而在后面再次创建这些字面常量时,就会直接从常量池中查找,如果找到了则直接对变量赋值,如果没找到,则先存储到常量池中再对变量赋值。
注:
- intern():手动将字符串放到常量池中。
- Java为8种基本数据类型和String类都提供了常量池。
- ” “引起来的字符串都会放到常量池中。
String是一种不可变对象,是不能被修改的;所有涉及到修改字符串内容的操作都是创建一个新对象,然后修改新对象。
1. 直接修改
String s1 = "hello";
for (int i = 0; i < 100; i++){
s1 += i;
}
这种修改方式每次都会创建新的变量,然后在新的变量后面拼接i,最后让s1引用新的变量,如此这样重复100次。这样操作的消耗无疑是巨大的,每次都需要创建新的变量。
2. 借助StringBuffer或者StringBuilder
StringBuffer stringBuffer = new StringBuffer("hello");
for (int i = 0; i < 100; i++){
stringBuffer.append(i);
}
这种修改方式只会创建一次新的变量StringBuffer,然后每次都在这一个变量后面拼接i,拼接100次,最后调用StringBuffer的toString方法创建一个新的String对象,让s1引用这个对象;这样销毁就要小很多。
StringBuilder和StringBuffer的用法一样。
那么String、StringBuffer、StringBuilder有什么区别呢?