【javaSE】String类
String类的基本概念
String类是JavaSE中用于表示字符串的核心类,位于java.lang
包中。字符串是不可变的(immutable),即一旦创建,其内容无法被修改。所有对字符串的操作(如拼接、替换)都会返回一个新的String对象。
创建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对象
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()
的替换字符串中表示一个普通反斜杠时,需要同时满足两层转义:
- 先满足 Java 字符串的转义:用
\\
表示一个\
; - 再满足正则替换模式的转义:将第一步的结果再转义一次,即
\\
→\\\\
。
最终,就需要用 \\\\
来表示一个普通的反斜杠 \
。
拆分
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未采用同步处理,属于线程不安全操作。