1. Java中String的相关剖析
1.1 字符串的构建方式
在Java里,String类存在多种构造途径,下面为你介绍常见的四种方式。
//构建字符串
public static void main(String[] args) {
//1.利用字符串常量赋值
String str1 = "Hello World";
System.out.println(str1);
//2.通过new String构造
String str2 = new String("Hello World");
System.out.println(str2);
//3.使用字符数组构造
char[] charArray = new char[]{'H','e','l','l','o',' ','W','o','r','l','d'};
String str3 = new String(charArray);
System.out.println(str3);
//4.使用字节数组构造
byte[] byteArray = new byte[]{72,101,108,108,111,32,87,111,114,108,100};
String str4 = new String(byteArray);
System.out.println(str4);
}
1.2 字符串的存储原理
字符串常量池是Java用于优化字符串存储与性能的机制,它实质是一个固定大小的HashTable,能通过共享字符串字面量来节省内存并提升性能。其工作原理如下:
- 字面量创建:当代码中使用字符串字面量(比如"Hello World")时,Java会先检查字符串常量池中是否已有相同的字符串。若存在,就直接返回池中字符串的引用;若不存在,则在池中创建新的字符串对象。
- new关键字创建:使用new来创建字符串对象时,即便字符串常量池中已经有相同的字符串,Java也会新创建一个字符串实例。
//字符串存储原理
public static void main(String[] args) {
String str1 = "Hello World";
String str2 = "Hello World";
String str3 = new String("Hello World");
System.out.println(str1 == str2); //true
System.out.println(str1 == str3); //false
}
1.3 字符串常用方法详解
1.3.1 字符串的比较
- 使用==比较:对于基本类型,比较的是变量里的值;对于引用类型,比较的是引用的地址。
//使用==进行比较
public static void main(String[] args) {
int num1 = 1;
int num2 = 1;
int num3 = 2;
System.out.println(num1 == num2); //true
System.out.println(num1 == num3); //false
String strA = new String("Hello World");
String strB = new String("Hello World");
System.out.println(strA == strB); //false
}
- 使用equals方法比较:Object类中equals默认是按照==来比较的;但String类重写了equals方法,现在是按照字典序来比较,若内容相同则返回true,不同则返回false。
//使用equals方法进行比较
public static void main(String[] args) {
String str1 = new String("Hello World");
String str2 = new String("Hello World");
String str3 = new String("hello world");
System.out.println(str1.equals(str2)); //true
System.out.println(str1.equals(str3)); //false
}
- 使用compareTo方法比较
- 逐字符比较:从两个字符串的第一个字符开始,逐个字符进行Unicode值的比较。若某个位置的字符不同,就返回这两个字符的Unicode值之差。
- 长度比较:如果所有对应字符都相同,但其中一个字符串比另一个长,就返回两个字符串长度之差。
//使用compareTo方法进行比较
public static void main(String[] args) {
String str1 = new String("Hello World");
String str2 = new String("Hello World");
String str3 = new String("hello world");
String str4 = new String("Hello");
System.out.println(str1.compareTo(str2)); //返回0
System.out.println(str1.compareTo(str3)); //返回-32,'H' - 'h'
System.out.println(str1.compareTo(str4)); //返回6,str1比str4长6个字符
}
1.3.2 字符串的查找
char charAt(int index)
:返回指定index下标处的字符,如果index为负数或者越界,会抛出StringIndexOutOfBoundsException异常。
//charAt
public static void main(String[] args) {
String str = "0123456789";
System.out.println(str.charAt(0)); //0
System.out.println(str.charAt(100)); //StringIndexOutOfBoundsException
System.out.println(str.charAt(-1)); //StringIndexOutOfBoundsException
}
int indexOf(int ch)
:返回指定字符在字符串中第一次出现的索引位置。如果字符未在字符串中找到,则返回-1。参数以Unicode代码点(int类型)形式传入。
//indexOf
public static void main(String[] args) {
String str = "HelloWorld";
//H的Unicode值:72
System.out.println(str.indexOf(72)); //返回H的下标0
System.out.println(str.indexOf(1)); //返回-1
}
int indexOf(int ch, int fromIndex)
:从fromIndex下标开始,返回指定字符在字符串中第一次出现的索引位置。如果字符未在字符串中找到,则返回-1。参数以Unicode代码点(int类型)形式传入。
//indexOf
public static void main(String[] args) {
String str = "HelloHello";
//H的Unicode值:72
System.out.println(str.indexOf(72, 3)); //返回第二个H的下标5
}
int indexOf(String str)
:返回指定字符串在字符串中第一次出现的索引位置。如果字符串未在原字符串中找到,则返回-1。
//indexOf
public static void main(String[] args) {
String str = "HelloWorld";
//H的Unicode值:72
System.out.println(str.indexOf("H")); //返回H的下标0
System.out.println(str.indexOf('H')); //返回H的下标0
System.out.println(str.indexOf("Z")); //返回-1
System.out.println(str.indexOf('Z')); //返回-1
}
int indexOf(String str, int fromIndex)
:从fromIndex下标开始,返回指定字符串在字符串中第一次出现的索引位置。如果字符串未在原字符串中找到,则返回-1。
//indexOf
public static void main(String[] args) {
String str = "HelloHello";
System.out.println(str.indexOf("H", 3)); //返回第二个H的下标5
}
1.3.3 字符串转换
valueOf
:能将不同的数据类型转换为字符串。
//valueOf
public static void main(String[] args) {
String str1 = String.valueOf(10);
System.out.println(str1); //10
String str2 = String.valueOf(10.0);
System.out.println(str2); //10.0
String str3 = String.valueOf(true);
System.out.println(str3); //true
}
- 字符串转换为其他数据类型
public static void main(String[] args) {
int num1 = Integer.parseInt("12345");
System.out.println(num1); //12345
double num2 = Double.parseDouble("12345.0");
System.out.println(num2); //12345.0
boolean flag = Boolean.parseBoolean("true");
System.out.println(flag); //true
}
String toUpperCase()
:将字符串中的所有字符转换为大写形式String toLowerCase()
:将字符串中的所有字符转换为小写形式
//String toUpperCase()
//String toLowerCase()
public static void main(String[] args) {
String str1 = "Hello World";
System.out.println(str1.toLowerCase()); //hello world
String str2 = "Hello World";
System.out.println(str2.toUpperCase()); //HELLO WORLD
}
char[] toCharArray()
:将字符串转换为字符数组
//toCharArray
public static void main(String[] args) {
String str = "Hello World";
char[] charArr = str.toCharArray();
for (char c : charArr) {
System.out.print(c + " ");
}
//输出结果:H e l l o W o r l d
System.out.println();
}
static String format(String format, Object... args)
:通过格式化字符串和可变参数生成格式化后的字符串输出
//format
public static void main(String[] args) {
String name = "Alice";
int age = 30;
String result1 = String.format("Name: %s, Age: %d", name, age);
System.out.println(result1); //Name: Alice, Age: 30
String result2 = String.format("%d-%d-%d", 2025, 6,12);
System.out.println(result2); //2025-6-12
}
1.3.4 字符串替换
方法 | 功能 |
---|---|
String replaceAll(String regex, String replacement) |
将所有匹配regex的部分替换为replacement |
String replaceFirst(String regex, String replacement) |
将首个匹配regex的部分替换为replacement |
//replaceAll
//replaceFirst
public static void main(String[] args) {
String str = "Hello World";
String newStr1 = str.replaceAll("l", "_");
System.out.println(newStr1); //He__o Wor_d
String newStr2 = str.replaceFirst("l", "_");
System.out.println(newStr2); //He_lo World
}
1.3.5 字符串拆分
方法 | 功能 |
---|---|
String[] split(String regex) |
根据正则表达式regex将字符串分割成数组 |
String[] split(String regex, int limit) |
根据正则表达式regex将字符串分割成数组,并通过limit参数控制分割后的数组数量 |
正则表达式(Regular Expression,简称 regex 或 regexp)是一种用于匹配字符串中字符模式的强大工具。它广泛应用于文本搜索、替换、验证和数据提取等场景。正则表达式由一系列字符和特殊符号组成,这些符号定义了搜索模式。
1.基本语法
- 普通字符:匹配自身。例如,
a
匹配字符 “a”- 元字符:具有特殊含义的字符,如
.
、*
、+
、?
、^
、$
、[]
、()
、{}
、|
等2.常用元字符
.
(点):匹配除换行符之外的任何单个字符。示例:a.b
匹配 “aab”、“acb”、“a3b” 等^
(脱字符):匹配字符串的开始。示例:^Hello
匹配以 “Hello” 开头的字符串$
(美元符):匹配字符串的结束。示例:world$
匹配以 “world” 结尾的字符串[]
(方括号):定义一个字符集,匹配其中任意一个字符。示例:[abc]
匹配 “a”、“b” 或 “c”;范围表示法:[a-z]
匹配任意小写字母,[0-9]
匹配任意数字;否定:[^abc]
匹配除 “a”、“b”、“c” 之外的任意字符|
(竖线):表示“或”关系。示例:cat|dog
匹配 “cat” 或 “dog”()
(圆括号):用于分组,可以提取子匹配或应用量词。示例:(ab)+
匹配一个或多个连续的 “ab”- 量词:
*
:匹配前面的表达式零次或多次。示例:ab*c
匹配 “ac”、“abc”、“abbbc” 等+
:匹配前面的表达式一次或多次。示例:ab+c
匹配 “abc”、“abbbc” 等,但不匹配 “ac”?
:匹配前面的表达式零次或一次。示例:ab?c
匹配 “ac” 或 “abc”{n}
:匹配前面的表达式恰好 n 次。示例:a{3}
匹配 “aaa”{n,}
:匹配前面的表达式至少 n 次。示例:a{2,}
匹配 “aa”、“aaa”、“aaaa” 等{n,m}
:匹配前面的表达式至少 n 次,但不超过 m 次。示例:a{2,3}
匹配 “aa”、“aaa”
//split
public static void main(String[] args) {
String str1 = "Hello World";
String[] arr1 = str1.split(" ");
for (String s : arr1) {
System.out.println(s);
}
//Hello
//World
String str2 = "Hello World Hello World";
String[] arr2 = str2.split(" ", 2);
for (String s : arr2) {
System.out.println(s);
}
//Hello
//World Hello World
}
1.3.5 字符串截取
方法 | 功能 |
---|---|
String substring(int beginIndex) |
用于从字符串中截取子字符串,从指定的beginIndex下标开始,直至字符串末尾。返回的新字符串包含原字符串从beginIndex下标开始的剩余部分 |
String substring(int beginIndex, int endIndex) |
返回从beginIndex到endIndex-1的子字符串。若参数不合法(如负值或beginIndex > endIndex),抛出IndexOutOfBoundsException |
//substring
public static void main(String[] args) {
String str = "Hello World";
String subStr1 = str.substring(1); //[1,end)
System.out.println(subStr1); //ello World
String subStr2 = str.substring(1, 2); //[1,2)
System.out.println(subStr2); //e
}
1.3.6 去除空格
String trim()
:用于去除字符串两端的空白字符
//trim()
public static void main(String[] args) {
String str = " Hello World ";
String trimmedStr = str.trim();
System.out.println("[" + trimmedStr + "]"); //[Hello World]
}
1.3.7 intern方法

native String intern()
:用于将字符串对象动态添加到字符串常量池中,并返回池中的唯一引用。调用 intern() 时,JVM 会检查常量池中是否存在内容相同的字符串:
* 若存在,直接返回池中对象的引用
* 若不存在,将当前字符串对象添加到池中,并返回其引用

1.4 字符串的不可变性
字符串的不可变性指String对象一旦创建,其内容就无法更改。任何看似修改字符串的操作(如拼接、替换)实际上都会创建新的String对象。不可变性的实现原理是String类内部使用
" />private final
修饰的byte数组
存储数据,且不提供修改该数组的方法。
Java SE 13工具类相关深度解析
1.5 StringBuilder与StringBuffer
public static void main(String[] args) {
String str = "Hello";
str = str + "World";
System.out.println(str); //输出Hello World
}
在上述代码中,s + " world"
会创建一个新的String对象,原来的"Hello"对象保持不变。如果在循环中进行String的拼接,会产生很多临时对象。此时Java提供了StringBuilder 和StringBuffer
```java
public static void main(String[] args) {
//String
long start = System.currentTimeMillis();
String str = "";
for (int i = 0; i < 10000; i++) {
str = str + i;
}
long end = System.currentTimeMillis();
System.out.println(end - start); //输出结果在60左右
//StringBuilder
start = System.currentTimeMillis();