String类是JavaSE中用于表示字符串的核心类,位于java.lang包中。字符串是不可变的(immutable),即一旦创建,其内容无法被修改。所有对字符串的操作(如拼接、替换)都会返回一个新的String对象。
String类提供的构造方式非常多,常用的就以下三种:
String s1 = "hjk";
System.out.println(s1);
String s2 = new String("hello bit");
System.out.println(s2);
char[] array = {'h','e','l','l','o'};
String s3 = new String(array);
System.out.println(s3);可以通过这三种方法来创建一个新的String对象
字符串的比较是常见操作之一,比如:字符串排序。Java中总共提供了4中方式:
public static void main(String[] args) {
/*equals比较内容 ==比较的是...........
比较大小compareTo 1.对应字符比较2.分不出来看长度3.一样长返回0 compareToIgnoreCase忽略大小写比较*/
String s1 = new String("hello");
String s2 = new String("world");
String s3 = s1;
System.out.println(s1 == s2);
System.out.println(s1 == s3);
System.out.println(s2 == s3);
System.out.println("******************");
System.out.println(s1.equals(s2));
System.out.println(s1.equals(s3));
System.out.println(s2.equals(s3));
System.out.println("*******************");
System.out.println(s1.compareTo(s2));
System.out.println(s1.compareTo(s3));
System.out.println(s2.compareTo(s3));
s2 = "hello";
System.out.println("s2改变之后");
System.out.println(s1 == s2);
System.out.println(s1 == s3);
System.out.println(s2 == s3);
System.out.println("******************");
System.out.println(s1.equals(s2));
System.out.println(s1.equals(s3));
System.out.println(s2.equals(s3));
System.out.println("*******************");
System.out.println(s1.compareTo(s2));
System.out.println(s1.compareTo(s3));
System.out.println(s2.compareTo(s3));
}运行结果:

由结果来看,"=="使用时比较的是是否引用同一个对象,"equals","compareTo","compareToIgnoreCase"(与compareTo类似,只是这个比较时忽略字母大小写)这些使用时比较的是具体内容是否一致。
常见方法:
charAt(i)下标访问
indexOf找到对应字符的下标
lastIndexOf其中indexOf和lastIndexOf有不同的构造方法如下:

String s = "abcdefghijklmnabcdefg";
System.out.println(s.charAt(0));
System.out.println(s.indexOf('d'));
System.out.println(s.indexOf("efg"));
System.out.println(s.indexOf('a',5));
System.out.println(s.indexOf("efg",7));
System.out.println(s.lastIndexOf('g'));
System.out.println(s.lastIndexOf("efg"));
System.out.println(s.lastIndexOf('c',8));
System.out.println(s.lastIndexOf("efg",3));

转化
其他类型字符串化String.valueOf 也可以将对象化成 会调用toString
序列化反序列化
大小写转换 toUpperCase (只要涉及到String类型的转变,都不是在原有的字符串上转换)
toLowerCase
字符串和数组 to类型Array
格式化输出String s1 = String.valueOf(19.3);
String s2 = String.valueOf(true);
System.out.println(s1);
System.out.println(s2);
String s3 = String.valueOf(new String("hello world"));
System.out.println(s3);
char[] array = {'a','b','c','d'};
System.out.println(Arrays.toString(array));
String s = "Hello World";
System.out.println(s.toLowerCase());
System.out.println(s.toUpperCase());
String s0 = "hello";
// 字符串转数组
char[] ch = s0.toCharArray();
for (int i = 0; i < ch.length; i++) {
System.out.print(ch[i]);
}
System.out.println();
// 数组转字符串
String s00 = new String(ch);
System.out.println(s00);
String s4 = String.format("%d %d %d %f",1,2,3,1.2f);
System.out.println(s4);
public static void main(String[] args) {
/* 替换(扩展一下)全转 转字符串*/
String s = "qsc_56| \\/aa";
System.out.println(s.replaceFirst("a","|"));
System.out.println(s.replaceAll("a","\\\\"));
}
补充知识:java中'\'有转义的意义,如果想要单独表达'\'这个字符来说,需要先加一个转义字符\,即用"\\"表示'\'。
当你需要在 replaceAll() 的替换字符串中表示一个普通反斜杠时,需要同时满足两层转义:
\\ 表示一个 \;\\ → \\\\。最终,就需要用 \\\\ 来表示一个普通的反斜杠 \。
public static void main(String[] args) {
/*字符串拆分split \在idea中必须写成\\ \\可以用成转义字符 多个分隔符*/
String s = "2023\\1205\\002\\78";
String[] result = s.split("\\\\");
for(String str:result){
System.out.println(str);
}
String s1 = "2023\\1205\\002\\78";
String[] result1 = s1.split("\\\\",2);
for(String str:result1){
System.out.println(str);
}
}
public static void main(String[] args) {
/* 截取 substring
去除空格 trim只会去除左右两边的空格*/
String s = "helloworld";
System.out.println(s.substring(5));
System.out.println(s.substring(5,8));
String str = " 4 4 4 4 ";
System.out.println(str.trim());
}
需要注意的是,trim()去除空格只会去除两边的空格,保留中间的。substring截取的时候(5,8)为左闭右开区间。
String是一种不可变对象. 字符串中的内容是不可改变。字符串不可被修改,是因为
1. String类在设计时就是不可改变的,String类实现描述中已经说明了
以下来自JDK1.8中String类的部分实现:



String类中的字符实际保存在内部维护的value字符数组中,该图还可以看出:
1. String类被final修饰,表明该类不能被继承
2. value被修饰被final修饰,表明value自身的值不能改变,即不能引用其它字符数组,但是其引用空间中的内容可以修改。
2.所有涉及到可能修改字符串内容的操作都是创建一个新对象,改变的是新对象
网上有些人说:字符串不可变是因为其内部保存字符的数组被final修饰了,因此不能改变。
这种说法是错误的,不是因为String类自身,或者其内部value被final修饰而不能被修改。
final修饰类表明该类不想被继承,final修饰引用类型表明该引用变量不能引用其他对象,但是其引用对象中的内容是可以修改的。
真正不能被改变的原因是value成员变量是被private修饰的!!!
那么,如果我们确实想要修改字符串的值,到底有没有办法呢???
举个最简单的例子:
public static void main(String[] args) {
String s = "hello";
s += "world";
System.out.println(s);
}表面上看来,这似乎是一个很好的办法,又便捷又省事的修改了s的值。但是,在这个过程中可不只是看上去那么简单,会经历一个很复杂的过程。

可以看出,在这个过程中,创建了许多其他的对象,这会极大地降低程序效率,浪费时间空间。
public static void main(String[] args) {
long start = System.currentTimeMillis();
String s = "";
for (int i = 0; i < 10000; ++i) {
s += i;
}
long end = System.currentTimeMillis();
System.out.println(end - start);
start = System.currentTimeMillis();
StringBuffer sbf = new StringBuffer("");
for (int i = 0; i < 10000; ++i) {
sbf.append(i);
}
end = System.currentTimeMillis();
System.out.println(end - start);
start = System.currentTimeMillis();
StringBuilder sbd = new StringBuilder();
for (int i = 0; i < 10000; ++i) {
sbd.append(i);
}
end = System.currentTimeMillis();
System.out.println(end - start);
}
通过这段代码更能直观的体现出直接对String类进行修改时时间消耗很大。因此:尽量避免对String的直接需要,如果要修改建议尽量使用StringBuffer或者StringBuilder。
方法的使用:
public static void main(String[] args) {
StringBuffer sbf = new StringBuffer("hello");
sbf.append("world");
sbf.append(9.3f);
sbf.append(9);
System.out.println(sbf);
System.out.println(sbf.charAt(5));
System.out.println(sbf.length());
System.out.println(sbf.capacity());
sbf.setCharAt(0,'H');
System.out.println(sbf.indexOf("w"));
sbf.insert(5," 9 ");
System.out.println(sbf);
sbf.delete(5,7);
System.out.println(sbf);
sbf.deleteCharAt(11);
System.out.println(sbf);
sbf.replace(11,14,"");
System.out.println(sbf);
System.out.println(sbf.substring(0));
System.out.println(sbf.reverse());
System.out.println(sbf.toString());
}
从上述例子可以看出:String和StringBuff最大的区别在于String的内容无法修改,而StringBuff的内容可以修改。频繁修改字符串的情况考虑使用StringBuff。
注:StringBuff和StringBuilder只有细微差别。
总结:
String、StringBuffer、StringBuilder的区别
1 String的内容不可修改,StringBuffer与StringBuilder的内容可以修改.
2 StringBuffer与StringBuilder大部分功能是相似的
3 StringBuffer采用同步处理,属于线程安全操作;而StringBuilder未采用同步处理,属于线程不安全操作。