9.1 String 类(不可变字符串,java.lang 包无需导入)
String 特点:字符串一旦创建,内容不能修改,底层 char 数组(Java9+byte 数组),每次拼接都会生成新 String 对象。
9.1.1 构造 String 对象(4 种常用构造方式)
直接字面量(推荐,复用常量池)
String s1 = "hello"; // 存字符串常量池,重复创建会复用
String s2 = "hello";System.out.println(s1 == s2); // true,同一常量池对象
new String (String 字符串),强制新建堆对象
String s3 = new String("hello");
System.out.println(s1 == s3); // false,堆中新对象
System.out.println(s1.equals(s3)); // true,内容相等
char 数组构造
char\[\] arr = {'J','a','v','a'};
String s4 = new String(arr);
System.out.println(s4); // Java
String 变量名 = new String(char\[\] 字符数组); //就是 把一个 char 数组,转换成一个完整的 String 字符串。
byte 字节数组构造(解码)
byte\[\] b = {97,98,99};
String s5 = new String(b);
System.out.println(s5); // abc
9.1.2 String 类的常用方法
- 获取长度、字符、索引
String str = "Java面向对象";
// 长度
System.out.println(str.length());// 8
// 根据下标取字符
System.out.println****(str.charAt(2****)); // v
// 查找字符第一次出现下标
System.out.println(str.indexOf('面')); // 4// 查找最后一次下标
System.out.println(str.lastIndexOf('a')); // 3
- 截取字符串 substring
String s = "abcdef";
System.out.println(s.substring(2)); // cdef 从下标2到末尾
System.out.println(s.substring(1,4)); // bcd 左闭右开[1,4)
- 大小写转换
String s = "HelloJava";
System.out.println(s.toUpperCase()); // HELLOJAVA
System.out.println(s.toLowerCase()); // hellojava
- 去除首尾空格 trim ()
String s = " 测试 ";
System.out.println(s.trim()); // "测试" 中间空格保留
- 判断开头结尾
String url = "https://www.baidu.com";System.out.println(url.startsWith("https"));
// true
System.out.println(url.endsWith(".com")); // true
- 内容比较
==:比较对象地址
equals():比较字符串内容(区分大小写)
equalsIgnoreCase():忽略大小写比较
String a = "ABC", b = "abc";
System.out.println(a.equals(b)); // false
System.out.println(a.equalsIgnoreCase(b)); // true
9.1.3 String 与基本数据类型相互转换
- 基本类型 → String
两种方式:String.valueOf(数据) / 数据 +""
int num = 123;
String s1 = String.valueOf(num);
String s2 = num + "";
System.out.println(s1+s2); // 123123
- String → 基本类型(包装类静态 parseXxx)
String numStr = "666";
int i = Integer.parseInt(numStr);
double d = Double.parseDouble("3.14");
boolean flag = Boolean.parseBoolean("true");
System.out.println(i + d); // 669.14
9.1.4 对象的 String 表示 toString ()
所有对象都继承 Object 的 toString (),默认返回类名@哈希地址,建议重写打印自定义信息。 示例:自定义学生类
class Student{
String name;
int age;
public Student(String name,int age){
this.name = name;
this.age = age;
}
// 重写toString
@Override
public String toString() {
return "学生{姓名:"+name+",年龄:"+age+"}";
}}public class Test{
public static void main(String\[\] args) {
Student stu = new Student("张三",18);
System.out.println(stu); // 自动调用toString()
// 输出:学生{姓名:张三,年龄:18}
}}
9.1.5 字符序列与字符、字节数组转换
String ↔ char \[\] 字符数组转换(最常用)
- String → char\[\] :toCharArray()
把字符串拆成一个个字符,放进数组。
String str = "Java面向对象";
// 字符串 → 字符数组
char\[\] chs = str.toCharArray();
结果:
chs0 = 'J'
chs1 = 'a'
chs2 = 'v'
chs3 = 'a'
chs4 = '面'
...
- char\[\] → String :new String(char\[\])
把字符数组拼成字符串。
char\[\] arr = {'J','a','v','a'};
String s = new String(arr); // 结果:"Java"
三、String ↔ byte \[\] 字节数组转换(编码 / 解码)
- String → byte\[\] :getBytes()一个中文字有三个字节
编码:把字符串变成计算机能存的字节(UTF-8 最常用)。
String str = "中文";byte\[\] bytes = str.getBytes(); // 转成字节数组
- byte\[\] → String :new String(byte\[\])
解码:把字节数组还原成字符串。
byte\[\] b = {97, 98, 99};String s = new String(b); // 结果:"abc"
四、3 句口诀记住所有转换
字符串变字符数组 → toCharArray()
字符数组变字符串 → new String(数组)
字符串变字节数组 → getBytes()
字节数组变字符串 → new String(数组)
9.2 正则表达式(匹配、替换、分割字符串,Pattern/Matcher 底层)
9.2.1 正则元字符(核心匹配符号)
表格
|-------|--------------|-------------------|--------------------------|
| 元字符 | 作用 | 示例 | |
| \d | 数字 0-9 | \\d{6} 匹配 6 位数字 | |
| \w | 字母、数字、下划线 | a-zA-Z0-9_ | |
| \s | 空白(空格、制表、换行) | | |
| . | 任意字符(除换行) | a.b 匹配 a1b、a#b | |
| ^ | 开头 | ^1 以 1 开头 | |
| | 结尾 | 9 以 9 结尾 | |
| * | 0 次或多次 | \d* 任意个数字 | |
| + | 1 次或多次 | \d+ 至少 1 个数字 | |
| ? | 0 或 1 次 | \\d? 0/1 个数字 | |
| {n} | 恰好 n 次 | {6} 6 次 | |
| {n,m} | n~m 次 | {1,11} 1 到 11 位 | |
| \[\] | 字符集 | 0-9a-z 数字小写字母 | |
| () | 分组 | `(13 | 15)\d {9}` 13/15 开头手机号 |
反斜杠要加倍
示例:手机号正则 ^13-9\\d{9}$
String phone = "13812345678";
boolean match = phone.matches("^13-9\\d{9}$");
System.out.println(match); // true
9.2.2 常用正则场景
邮箱匹配:^\\w+@\\w+\\.(com|cn)$
. 在正则里是 "任意字符" 如果想表示 真正的点(.),必须写成 \\.
String email = [++++"test123@qq.com";++++](mailto:)
System.out.println(email.matches("^\\w+@\\w+\\.(com|cn)$")); // true
身份证 18 位:^\\d{17}0-9Xx$
纯数字校验:^\\d+$
想当功能用 → 直接写
- * . ? () \[\]
想当普通字符用 → 加 \
\\+ 加号本身
\\. 点本身
\\? 问号本身
Java 要写 4 个反斜杠 \\\\ 才能真正表示 1 个 \
9.2.3 字符序列的替换与分割(String 内置方法)
- split (String regex) 按正则分割字符串,返回数组
String str = "苹果,香蕉,橘子";
String\[\] fruits = str.split(",");
for(String f : fruits) System.out.println(f);
//把 fruits 数组里的每一个东西,挨个取出来,放进 f 里,然后打印
// 按数字分割
String s = "a1b2c3d";
String\[\] arr = s.split("\\d");
System.out.println(arr0+arr1+arr2+arr3); // abcd
- replaceAll (String regex,String newStr) 正则全局替换
String text = "a1b2c3";
String res = text.replaceAll("\\d","*");
System.out.println(res); // a*b*c*
// 过滤所有中文
String s = "java语言888";
String clear = s.replaceAll("\\\\u4e00-\\\\u9fa5","");
System.out.println(clear); // java888
9.3 StringTokenizer 类(老式字符串分割工具,java.util)
区别于 split:基于分隔符标记分割,不支持正则,分割效率高,迭代遍历 构造:StringTokenizer(字符串,分隔符) 常用方法:
hasMoreTokens():是否还有分割片段
nextToken():取出下一段
countTokens():总片段数量 示例:
// 1. 必须导入工具类,不然程序找不到
StringTokenizerimport java.util.StringTokenizer;
public class TestToken {
public static void main(String\[\] args) {
// 2. 原始字符串:用逗号隔开4个数字
String data = "100,200,300,400";
// 3. 创建分割器对象
// 第一个参数:要切割的字符串 data
// 第二个参数:分隔符 , (按逗号切分)
StringTokenizer st = new StringTokenizer(data,",");
// 4. countTokens():统计还剩下多少段没读取
System.out.println("片段总数:"+st.countTokens()); //输出4
// 原理:字符串被逗号切成 100、200、300、400 一共4段
// 5. while循环:判断是否还有没读完的片段
// hasMoreTokens() 返回 true = 还有片段没取;false = 全部读完
while(st.hasMoreTokens()){
// 6. nextToken():取出当前这一段,指针自动往后走一格
String num = st.nextToken();
// 打印取出的片段
System.out.print(num+" ");
}
}}
9.4 Scanner 类(控制台输入、文件读取,java.util)
作用:读取控制台键盘输入,支持基本类型、字符串
核心方法
next():读取一段不含空格的字符串
nextLine():读取整行(含空格)
nextInt()/nextDouble ():读取数字 示例:控制台录入姓名、年龄
import java.util.Scanner;
public class TestScanner {
public static void main(String\[\] args) {
Scanner sc = new Scanner(System.in);
System.out.print("输入姓名:");
String name = sc.nextLine();
System.out.print("输入年龄:");
int age = sc.nextInt();
System.out.println("姓名:"+name+",年龄:"+age);
sc.close(); // 关闭流
}}
坑点:nextInt () 读取数字后会残留换行符,后续 nextLine () 会直接读空行,解决:多读一次空行sc.nextLine();
9.5 Pattern 与 Matcher(正则底层实现,复杂匹配、分组提取)
String s = "123456";
boolean res = s.matches("\\d{6}");
使用固定 4 步(背会这 4 步就无敌)
// 1. 写正则
String regex = "\\d+";
// 2. 编译正则 →
PatternPattern p = Pattern.compile(regex);
// 3. 创建匹配器 →
MatcherMatcher m = p.matcher("abc123def456");
// 4. 使用Matcher方法
m.find(); // 查找
m.group(); // 取找到的内容
完整示例 1:查找数字
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class TestPattern {
public static void main(String\[\] args) {
String str = "Java123Python456";
String regex = "\\d+"; // 匹配数字
// 1. 编译
Pattern p = Pattern.compile(regex);
// 2. 匹配器
Matcher m = p.matcher(str);
// 3. 循环查找所有数字
while(m.find()){
System.out.println("找到:" + m.group());
}
}}
输出:
找到:123
找到:456
完整示例 2:判断邮箱
String regex = "\\w+@\\w+\\.com";
Pattern p = Pattern.compile(regex);
Matcher m = p.matcher("test@qq.com");
boolean ok = m.matches();
System.out.println(ok); // true
9.6 StringBuffer 类(可变字符串,线程安全;同类 StringBuilder 线程不安全、速度更快)
String 不可变,大量拼接用 StringBuffer/Builder 避免生成大量中间对象。
9.6.1 StringBuffer 对象创建
三种构造:
// 空缓冲区,默认容量16
StringBuffer sb1 = new StringBuffer();
// 指定初始容量
StringBuffer sb2 = new StringBuffer(50);
// 用字符串初始化
StringBuffer sb3 = new StringBuffer("java");
9.6.2 StringBuffer 常用方法(全部修改自身,不产生新对象)
append () 追加(最常用,支持所有类型)
StringBuffer sb = new StringBuffer();
sb.append("数字:").append(123).append(",布尔:").append(true);
System.out.println(sb); //数字:123,布尔:true
insert (下标,内容) 指定位置插入
StringBuffer sb = new StringBuffer("abc");
sb.insert(1,"X");System.out.println(sb); //aXbc
delete (start,end) 删除区间字符
StringBuffer sb = new StringBuffer("123456");
sb.delete(2,4);System.out.println(sb); //1256
reverse () 字符串反转
StringBuffer sb = new StringBuffer("abcde");
sb.reverse();System.out.println(sb); //edcba
replace (start,end, 新串) 区间替换
StringBuffer sb = new StringBuffer("0000");
sb.replace(1,3,"99");System.out.println(sb); //0990
转 String:toString ()
String res = sb.toString();
|---------------|-----|---------|-------------|----------------|
| 类 | 可变性 | 线程安全 | 性能 | 适用场景 |
| String | 不可变 | 安全 | 差(频繁拼接大量对象) | 少量字符串、常量 |
| StringBuffer | 可变 | 加同步锁,安全 | 较慢 | 多线程下字符串拼接 |
| StringBuilder | 可变 | 无锁,不安全 | 最快 | 单线程大量拼接(开发最常用) |
9.7 日期与时间(java.time 包 Java8 全新时间 API,替代老旧 Date/SimpleDateFormat)
9.7.1 java.time 核心类(推荐全部使用,无线程安全问题)
LocalDate:只存年月日(日期)
LocalTime:只存时分秒(时间)
LocalDateTime:年月日时分秒(完整日期时间)
Instant:时间戳(毫秒,机器时间)
Duration:时分秒时间差
Period:年月日日期差
示例 1:获取当前时间
import java.time.*;
public class TestTime {
public static void main(String\[\] args) {
LocalDate date = LocalDate.now(); // 当前日期 2026-06-08
LocalTime time = LocalTime.now(); // 当前时分秒
LocalDateTime dt = LocalDateTime.now(); // 完整时间
System.out.println(date);
System.out.println(time);
System.out.println(dt);
}}
示例 2:自定义指定时间
LocalDate birthday = LocalDate.of(2005,5,20);
LocalDateTime dt = LocalDateTime.of(2026,6,8,14,30);
9.7.2 日期、时间差和日历
Period 计算年月日差
LocalDate d1 = LocalDate.of(2020,1,1);
LocalDate d2 = LocalDate.of(2026,6,8);
Period p = Period.between(d1,d2);
System.out.println("相差:"+p.getYears()+"年"+p.getMonths()+"月"+p.getDays()+"日");
Duration 计算时分秒毫秒差
LocalTime t1 = LocalTime.of(9,0);
LocalTime t2 = LocalTime.of(18,30);
Duration dur = Duration.between(t1,t2);
System.out.println("相差小时:"+dur.toHours());
日期增减操作(plus/minus,返回新时间对象,原对象不变)
LocalDate today = LocalDate.now();
LocalDate nextWeek = today.plusWeeks(1); //加一周
LocalDate lastMonth = today.minusMonths(1); //减一月
加:plus 减:minus
后面跟上你要加 / 减的单位:
Years → 年
Months → 月
Days → 日
Hours → 时
Minutes → 分
Seconds → 秒
9.7.3 日期格式化 DateTimeFormatter(线程安全,替代 SimpleDateFormat)
格式化时间 → 字符串、字符串 → 时间
import java.time.format.DateTimeFormatter;
public class TestFormat {
public static void main(String\[\] args) {
LocalDateTime now = LocalDateTime.now();
// 定义格式模板
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
// 时间转字符串
String timeStr = now.format(formatter);
System.out.println(timeStr);
// 字符串转回时间
String str = "2026-06-08 15:20:00";
LocalDateTime parseDt = LocalDateTime.parse(str,formatter);
System.out.println(parseDt);
}}
格式符号说明:
yyyy:4 位年份,MM:两位月份,dd:两位日期
HH:24 小时制,mm:分钟,ss:秒
例子:
"yyyy-MM-dd HH:mm:ss"
→ 2026-06-08 14:30:00
"yyyy/MM/dd"
→ 2026/06/08
"yyyy年MM月dd日 HH:mm"
→ 2026年06月08日 14:30
9.8 Math、BigInteger 和 Random 类
9.8.1 Math 类(java.lang,静态数学工具,全静态方法,无需 new)
1)Math.abs(数字) → 求绝对值
System.out.println(Math.abs(-10)); // 10
2)Math.max(a,b) → 取最大
System.out.println(Math.max(5, 9)); // 9
3)Math.min(a,b) → 取最小
System.out.println(Math.min(5,9)); //5
4)Math.round(小数) → 四舍五入
System.out.println(Math.round(3.6)); //4
5)Math.ceil(小数) → 向上取整
System.out.println(Math.ceil(2.1)); //3.0
6)Math.floor(小数) → 向下取整
System.out.println(Math.floor(2.9)); //2.0
7)Math.pow(a,b) → a 的 b 次方
System.out.println(Math.pow(2,3)); //8.0 2³
8)Math.sqrt(数字) → 开平方
System.out.println(Math.sqrt(16)); //4.0
- Math.random () 随机数
生成 0.0 ~ 1.0 之间的随机小数
double d = Math.random();
想生成 1~100 整数:
int num = (int)(Math.random() * 100) + 1;
9.8.2 BigInteger 类(java.math,超大整数,超出 long 范围时使用)
long 最大值:9223372036854775807,超过只能用 BigInteger,支持加减乘除取模
import java.math.BigInteger;
public class TestBigInt {
public static void main(String\[\] args) {
BigInteger a = new BigInteger("9999999999999999999999");
BigInteger b = new BigInteger("2");
// 运算,返回新BigInteger对象
BigInteger add = a.add(b); //加
BigInteger sub = a.subtract(b); //减
BigInteger mul = a.multiply(b); //乘
BigInteger div = a.divide(b); //除
System.out.println(add);
}}
9.8.3 Random 类(java.util,生成伪随机数,比 Math.random 灵活)
import java.util.Random;
public class TestRandom {
public static void main(String\[\] args) {
Random r = new Random();
// 随机int(正负都有)
System.out.println(r.nextInt());
// 0~9随机整数 [0,10)
System.out.println(r.nextInt(10));
// 1~10随机整数
System.out.println(r.nextInt(10)+1);
// 随机小数 [0,1)
System.out.println(r.nextDouble());
// 随机布尔
System.out.println(r.nextBoolean());
}}
固定种子 Random (100):每次运行随机序列完全相同,用于测试复现。
- nextInt(数字) → 生成 0 ~ 数字 - 1 的随机整数
r.nextInt(10); // 0 ~ 9
r.nextInt(3); // 0 ~ 2
- 想生成 1 ~ 10 怎么办?
int num = r.nextInt(10) + 1;
公式:
plaintext
r.nextInt(最大值) + 1
- nextDouble() → 0.0 ~ 1.0 之间随机小数
double d = r.nextDouble();
- nextBoolean() → 随机 true /false
boolean b = r.nextBoolean();