1,String原理介绍
1.1 String 构造
//使用字符串常量进行赋值
String s1 = "hello world";
System.out.println(s1);
//直接new String对象
String s2 = new String("hello world");
System.out.println(s2);
//使用字符组进行构造
char[] array = {'h','e','l','l','o'};
String s4 = new String(array);
System.out.println(s4);
查看源码发现:String是引用类型,内部并不存储字符串本身

1.2 字符串常量池(StringTable)
字符串常量池在JVM是StringTable类,实际上是一个固定的HashTable(哈希表),字符串常量池在堆上。
1.3 字符串内存存储
public static void main(String[] args) {
String str1 = "abc";
String str2 = "abc";
System.out.println(str1 == str2);
}
//true

- str1在进行存储的时候,“abc”会存储到字符串常量池当中
- 当str2再次存储的时候,先会检查字符串常量池当中是否存在"abc"常量,如果存在,则不再重复存储
public static void main(String[] args) {
String str1 = new String("abc");
String str2 = new String("abc");
System.out.println(str1 == str2);
}
//false

- 第一次存储的时候,会将“abc"存储到常量池当中
- 每次new都会在堆中实例化新的对象
- 存储str2的时候,会使用常量池的"abc”对象进行存储
2,常用方法介绍
2.1 ==比较是否引用同一个对象
内置类型,比较的是变量中的值;对于引用类型比较的是引用中的地址
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 s1 = new String("hello");
String s2 = new String("hello");
String s3 = new String("world");
String s4 = s1;
System.out.println(s1 == s2); // false
System.out.println(s2 == s3); // false
System.out.println(s1 == s4); // true
}
2.2 equals 方法:按字典序比较
字典序:字符大小的顺序
String类重写了父类Object中equals⽅法,Object中equals默认按照==⽐较,String重写equals⽅法 后,按照如下规则进⾏⽐较
public boolean equals(Object anObject) {
if (this == anObject) {
return true;
}
return (anObject instanceof String aString)
&& (!COMPACT_STRINGS || this.coder == aString.coder)
&& StringLatin1.equals(value, aString.value);
}
@IntrinsicCandidate
public static boolean equals(byte[] value, byte[] other) {
if (value.length == other.length) {
for (int i = 0; i < value.length; i++) {
if (value[i] != other[i]) {
return false;
}
}
return true;
}
return false;
}
示例
public static void main(String[] args) {
String s1 = new String("hello");
String s2 = new String("hello");
String s3 = new String("Hello");
// s1、s2、s3引⽤的是三个不同对象,因此==⽐较结果全部为false
System.out.println(s1 == s2); // false
System.out.println(s1 == s3); // false
// equals⽐较:String对象中的逐个字符
// 虽然s1与s2引⽤的不是同⼀个对象,但是两个对象中放置的内容相同,因此输出true
// s1与s3引⽤的不是同⼀个对象,⽽且两个对象中内容也不同,因此输出false
System.out.println(s1.equals(s2)); // true
System.out.println(s1.equals(s3)); // false
}
2.3 compareTo 方法:按字典序进行比较
与equals不同的是,equals返回的是boolean类型,而compareTo返回的是int类型。
- 先按照字典序次序大小比较,如果出现不等的字符,直接返回这两个字符的大小差值
- 如果前k个字符相等(k为两个字符长度最小值),返回值:两个字符串长度差值
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");
System.out.println(s1.compareTo(s2)); // 不同输出字符差值-1
System.out.println(s1.compareTo(s3)); // 相同输出 0
System.out.println(s1.compareTo(s4)); // 前k个字符完全相同,输出⻓度差值 -3
}
2.4 compareToIgnoreCase 方法:与compareTo方法相同,但是忽略大小写
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");
System.out.println(s1.compareToIgnoreCase(s2)); // 不同输出字符差值-1
System.out.println(s1.compareToIgnoreCase(s3)); // 相同输出 0
System.out.println(s1.compareToIgnoreCase(s4)); // 前k个字符完全相同,输出⻓度差值 -3
}
2.5 字符串查找
| 方法 | 功能 |
|---|---|
| char charAt(int index) | 返回index位置上字符,如果index为负数或者越界,抛出IndexOutOfBoundsException异常 |
| int indexOf(int ch) |
返回ch第一次出现的位置,没有返回-1 |
| int indexOf(int ch,int fromIndex) | 从fromIndex位置出现找ch第一次出现的位置,没有返回-1 |
| int indexOf(String str) | 返回str第一次出现的位置,没有返回-1 |
| int indexOf(String str,int fromIndex) | 从fromIndex位置开始找str第一次出现的位置,没有返回-1 |
| int lastIndexOf(int ch) | 从后往前找,返回ch第一次出现的位置,没有返回-1 |
| int lastIndexOf(int ch,int fromIndex) |
从fromIndex位置开始找,从后往前找ch第一次出现的位置,没有返回-1 |
| int lastIndexOf(String str) | 从后往前找,返回str第一次出现的位置,没有返回-1 |
| int lastIndesOf(String str,int fromIndex) | 从fromIndex位置开始找,从后往前找str第一次出现的位置,没有返回-1 |
public static void main(String[] args) {
String s = "aaabbbcccaaabbbccc";
System.out.println(s.charAt(3)); // 'b'
System.out.println(s.indexOf('c')); // 6
System.out.println(s.indexOf('c', 10)); // 15
System.out.println(s.indexOf("bbb")); // 3
System.out.println(s.indexOf("bbb", 10)); // 12
System.out.println(s.lastIndexOf('c')); // 17
System.out.println(s.lastIndexOf('c', 10)); // 8
System.out.println(s.lastIndexOf("bbb")); // 12
System.out.println(s.lastIndexOf("bbb", 10)); // 3
}
2.6 转换
1. 数值和字符串转化
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("Hanmeimei", 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");
System.out.println(data1);
System.out.println(data2);
}
2. 大小写转换
public static void main(String[] args) {
String s1 = "hello";
String s2 = "HELLO";
// ⼩写转⼤写
System.out.println(s1.toUpperCase());
// ⼤写转⼩写
System.out.println(s2.toLowerCase());
}
3. 字符串转数组
public static void main(String[] args) {
String s = "hello";
// 字符串转数组
char[] ch = s.toCharArray();
for (char x :ch) {
System.out.print(x + " ");
}
System.out.println();
// 数组转字符串
String s2 = new String(ch);
System.out.println(s2);
}
4. 格式化
public static void main(String[] args) {
String s = String.format("%d-%d-%d", 2026, 6,1);
System.out.println(s);
}
2.7 字符串替换
String replaceAll(String regex,String replacement) 替换所有的指定内容
String replaceFirst(String regex,String replacement) 替换首个内容
String str = "helloworld" ;
System.out.println(str.replaceAll("l", "_"));
System.out.println(str.replaceFirst("l", "_"));
由于字符串是不可变对象,替换不修改当前字符串,而是产生一个新的字符串
2.8 字符串拆分
| 方法 | 功能 |
| String[] split(String regex) | 将字符串全部拆分 |
| String[] split(String regex,int limit) | 将字符串以指定的格式,拆分为limit组 |
public static void main(String[] args) {
String st1 = "hello world yes no";
String[] result = st1.split(" ");
for (String x : result) {
System.out.println(x);
}
//hello
//world
//yes
//no
}
部分拆分
public static void main(String[] args) {
String st1 = "hello world yes no";
String[] result = st1.split(" ",3);
for (String x : result) {
System.out.println(x);
}
//hello
//world
//yes no
}
由于split传的参数涉及正则表达式,所有有些需要特殊处理
拆分IP地址
String str = "192.168.1.1" ;
String[] result = str.split("\\.") ;
for(String s: result) {
System.out.println(s);
}
注意
- 字符“|” “*” “+”都得加上转义字符,前面加上“\\"
- 如果是“\"就写成“\\\\"
- 多个分隔符用 | 链接
多次拆分
String str = "name=zhangsan&age=18" ;
String[] result = str.split("&") ;
for (int i = 0; i < result.length; i++) {
String[] temp = result[i].split("=") ;
System.out.println(temp[0]+" = "+temp[1]);
}
public static void main(String[] args) {
String str = "name=zhangsan&age=18" ;
String[] result = str.split("=|&") ;
for (String s : result) {
System.out.println(s);
}
}
2.9 字符串的截取
| 方法 | 功能 |
| String substring(int beginIndex) | 从指定索引截取到结尾 |
| String substring(int beginIndex,int endIndex) | 截取部分内容 |
String str = "helloworld" ; System.out.println(str.substring(5)); System.out.println(str.substring(0, 5));
下标从0开始,范围是[ ),左闭右开
去除左右两边的空格
String trim() 去掉字符串中的左右空格,保留中间空格
String str = " hello world " ;
System.out.println("["+str+"]");
System.out.println("["+str.trim()+"]");
2.10 intern 方法
- 当调用 intern() 方法时,如果字符串常量池中已经包含一个等于此String对象的字符串(由equals(Object)方法确定),则返回常量池中的字符串
- 否则,将此String对象添加到常量池中,并返回此String对象的引用
public static void main(String[] args) {
char[] ch = new char[]{'a', 'b', 'c'};
String s1 = new String(ch); // s1对象并不在常量池中
//s1.intern(); // s1.intern();调⽤之后,会将s1对象的引⽤放⼊到常量池中
String s2 = "abc"; // "abc" 在常量池中存在了,s2创建时直接⽤常量池中"abc"的引⽤
System.out.println(s1 == s2);
}
// 输出false
// 将上述⽅法打开之后,就会输出true


3,字符串的不可变性
String是一种不可变对象,字符串中的内容是不可改变的。
所有涉及到可能修改字符串内容的操作都是创建一个新对象,改变的是新对象
String之所以不可以被修改的原因是内部数组为私有成员
4,字符串修改
public static void main(String[] args) {
String s = "hello";
s = s + " world";
System.out.println(s); // 输出:hello world
}
这种字符串拼接的操作,会产生临时对象,拼接一次创建一个新对象,为了执行效率java提供了StringBuffer和StringBuilder
4.1 StringBuilder
| 方法 | 说明 |
|---|---|
| StringBuilder append(String str) | 在尾部追加,相当于String的+= |
| char charAt(int index) | 获取index位置的字符 |
| int length() | 获取字符串的长度 |
| int capacity() | 获取底层保存字符串空间总的大小 |
| void ensureCapacity(int mininmumCapacity) |
确保容量至少等于规定的最小值 |
| void setCharAt(int index,char ch) | 将index位置的字符设置为ch |
| int indexOf(String str) | 返回str第一次出现的位置 |
| int indexOf(String str,int fromIndex) |
返回指定子串的第一次出现的字符串中的索引,从指定的索引开始 |
| int lastIndexOf(String str) | 返回最后一次出现str的位置 |
| int lastIndexOf(String str,int fromIndex) | 从fromIndex位置开始找str最后一次出现的 |
| StringBuilder insert(int offset,String str) | 从offset位置插入 |
| StringBuilder deleteCharAt(int index) | 删除index位置字符 |
| StringBuilder delete(int start,int end) | 删除[start,end)区间内的字符 |
| StringBuilder replace(int start,int end,String str) | 将[start,end)位置的字符替换为str |
| String substring(int start) | 从start开始一直到末尾的字符以String的形式返回 |
| String substring(int start,int end) | 从start开始一直到end的字符以String的形式返回 |
| StringBuilder reverse() | 反转字符串 |
| String toString() | 将所有字符按照String的方式返回 |
String Builder的内容可以修改
String和String Builder想要相互转换
- String变为StringBuilder: 利⽤StringBuilder的构造⽅法或append()⽅法
- StringBuilder变为String: 调⽤toString()⽅法
4.2 String Buffer
功能基本上和String Builder一样
StringBuffer采⽤同步处理,属于线程安全操作;⽽StringBuilder未采⽤同步处理,属于线程不安全操作












