Java常用类详解

O泡李华 9

Java 常用类详解

本章位置:Java 核心基础
学习目标:掌握 String、StringBuilder、包装类、Math、Random、BigDecimal、System、日期时间 API、正则表达式等常用类,并能够在实际业务代码中正确选择和使用。


一、为什么要学习 Java 常用类

学习面向对象之后,我们已经知道:

Java 中很多功能都是通过类和对象提供的

实际开发时,不可能所有功能都自己从零实现。

例如:

字符串处理
数学运算
随机数
金额计算
日期时间
类型转换
数组操作
正则校验

Java 标准库已经提供了大量可以直接使用的类。

例如:

String
StringBuilder
Integer
Double
Math
Random
BigDecimal
System
LocalDate
LocalDateTime
DateTimeFormatter
Pattern

这些类通常被统称为:

Java 常用类

二、Java API 是什么

API:

Application Programming Interface

可以理解为:

Java 官方已经写好的类、方法和功能,我们按照规定的方式调用即可。

例如:

Math.max(10, 20);

我们不需要自己重新编写“求最大值”的底层逻辑。


三、学习常用类的正确方式

常用类很多,不需要死记所有方法。

建议掌握:

1. 这个类解决什么问题

2. 常用方法有哪些

3. 方法返回什么

4. 哪些地方容易踩坑

5. 不熟悉时会查 API 文档

实际开发中:

记住核心用法
+
需要时查询官方文档

比死背几十个方法更加重要。


四、String 字符串

Java 中:

String

用于表示字符串。

例如:

String name = "张三";

String message = "Hello Java";

注意:

String 不是 Java 的 8 种基本数据类型

它是一个:

引用类型

五、创建 String

最常见:

String name = "张三";

也可以:

String name =
        new String("张三");

实际开发中一般优先使用:

String name = "张三";

六、字符串不可变

String 最重要的特点之一:

String 对象一旦创建,它保存的字符串内容本身不能被修改。

例如:

String str = "Java";

str = str + " Web";

看起来好像:

Java

被改成:

Java Web

实际上通常可以理解为:

创建了新的字符串对象

然后让 str 指向新的对象

原来的:

"Java"

并没有被直接修改。


七、为什么 String 设计成不可变

不可变带来很多好处:

安全
线程安全
字符串常量池可复用
hash 值稳定
便于作为 Map 键

初学阶段重点记住:

对 String 做“修改”操作时,经常是在产生新字符串。


八、字符串常量池

例如:

String s1 = "Java";

String s2 = "Java";

字符串字面量:

"Java"

通常会进入:

字符串常量池

相同字面量有机会被复用。

因此:

System.out.println(s1 == s2);

可能得到:

true

但不要因此养成用 == 比较字符串内容的习惯。


九、== 和 equals() 比较字符串

这是 Java 初学阶段非常重要的知识点。

==

对于引用类型:

主要比较是否指向同一个对象

equals()

String 重写了:

equals()

用于比较:

字符串内容是否相同

例如:

String s1 =
        new String("Java");

String s2 =
        new String("Java");

System.out.println(
        s1 == s2
);

System.out.println(
        s1.equals(s2)
);

通常输出:

false
true

十、字符串比较推荐写法

例如:

String username = "admin";

判断:

if ("admin".equals(username)) {

}

这种写法有一个好处:

即使:

username == null

也不会因为调用:

username.equals(...)

出现空指针。


十一、equalsIgnoreCase()

忽略英文字母大小写比较:

String a = "JAVA";

String b = "java";

System.out.println(
        a.equalsIgnoreCase(b)
);

输出:

true

常用于:

验证码之外的普通英文输入
命令
扩展名
简单标识

十二、String.length()

获取字符串长度:

String text = "Java";

System.out.println(
        text.length()
);

输出:

4

注意和数组区别:

数组:

array.length

字符串:

str.length()

一个没有括号,一个有括号。


十三、charAt()

获取指定索引位置的字符:

String text = "Java";

char c = text.charAt(0);

System.out.println(c);

输出:

J

索引同样从:

0

开始。


十四、遍历字符串

String text = "Java";

for (int i = 0;
     i < text.length();
     i++) {

    System.out.println(
            text.charAt(i)
    );
}

输出:

J
a
v
a

十五、isEmpty()

判断字符串长度是不是 0:

String str = "";

System.out.println(
        str.isEmpty()
);

输出:

true

注意:

""

和:

null

不是一回事。


十六、空字符串和 null

空字符串

String str = "";

说明:

对象存在
但内容长度是 0

null

String str = null;

说明:

没有指向实际 String 对象

所以:

str.length();

会出现:

NullPointerException

十七、isBlank()

Java 11 以后:

isBlank()

可以判断:

空字符串
或只包含空白字符

例如:

System.out.println(
        "".isBlank()
);

System.out.println(
        "   ".isBlank()
);

都是:

true

十八、contains()

判断是否包含某段内容:

String text =
        "学习 Java SpringBoot";

System.out.println(
        text.contains("Java")
);

输出:

true

十九、startsWith() 和 endsWith()

判断开头:

String file =
        "avatar.jpg";

System.out.println(
        file.startsWith("avatar")
);

判断结尾:

System.out.println(
        file.endsWith(".jpg")
);

常见用途:

文件后缀判断
URL 判断
字符串前缀匹配

二十、indexOf()

查找某个字符或字符串第一次出现的索引:

String text =
        "hello java";

int index =
        text.indexOf("java");

System.out.println(index);

如果找不到:

返回 -1

例如:

System.out.println(
        text.indexOf("python")
);

结果:

-1

二十一、lastIndexOf()

查找最后一次出现的位置:

String text =
        "a-b-c-b";

System.out.println(
        text.lastIndexOf("b")
);

二十二、substring()

截取字符串。

例如:

String text =
        "HelloJava";

String result =
        text.substring(5);

System.out.println(result);

输出:

Java

二十三、substring(begin, end)

例如:

String text =
        "HelloJava";

String result =
        text.substring(
                0,
                5
        );

输出:

Hello

规则:

包含 begin

不包含 end

也就是常说的:

左闭右开

二十四、replace()

替换字符串:

String text =
        "Java is good";

String result =
        text.replace(
                "Java",
                "Spring"
        );

结果:

Spring is good

原字符串不会直接改变。


二十五、replaceAll()

replaceAll() 支持:

正则表达式

例如:

String text =
        "abc123def456";

String result =
        text.replaceAll(
                "\\d+",
                "*"
        );

结果类似:

abc*def*

二十六、toUpperCase() 和 toLowerCase()

转大写:

String text = "java";

System.out.println(
        text.toUpperCase()
);

结果:

JAVA

转小写:

"JAVA".toLowerCase()

结果:

java

二十七、trim()

去掉字符串:

首尾传统空格

例如:

String text =
        "   Java   ";

System.out.println(
        text.trim()
);

结果:

Java

二十八、strip()

Java 11 以后:

strip()

对 Unicode 空白字符处理更完善。

例如:

String result =
        text.strip();

现代 Java 中通常更推荐理解和使用:

strip()

二十九、split()

按照指定规则切割字符串。

例如:

String text =
        "Java,MySQL,Spring";

String[] array =
        text.split(",");

遍历:

for (String item : array) {

    System.out.println(item);
}

输出:

Java
MySQL
Spring

三十、split() 参数是正则表达式

这是容易踩坑的地方。

例如:

.
|
+
*

等字符在正则中有特殊含义。

如果按点切割:

String ip =
        "192.168.1.1";

不能简单写:

ip.split(".");

应该:

ip.split("\\.");

三十一、String.join()

拼接多个字符串:

String result =
        String.join(
                "-",
                "2026",
                "09",
                "09"
        );

结果:

2026-09-09

三十二、String.valueOf()

把其他类型转换成字符串:

int age = 20;

String text =
        String.valueOf(age);

例如:

String.valueOf(3.14);
String.valueOf(true);

都很常用。


三十三、toCharArray()

字符串转换成字符数组:

String text =
        "Java";

char[] chars =
        text.toCharArray();

然后:

for (char c : chars) {

    System.out.println(c);
}

三十四、字符串反转

String 本身没有直接:

reverse()

可以借助:

StringBuilder

例如:

String text =
        "Java";

String result =
        new StringBuilder(text)
                .reverse()
                .toString();

System.out.println(result);

结果:

avaJ

三十五、StringBuilder

StringBuilder 用于:

高效地进行字符串拼接和修改

例如:

StringBuilder builder =
        new StringBuilder();

添加:

builder.append("Java");

builder.append(" ");

builder.append("Spring");

最终:

String result =
        builder.toString();

三十六、为什么需要 StringBuilder

如果循环中大量使用:

String result = "";

for (...) {

    result = result + ...
}

可能不断创建新的 String 对象。

例如:

String result = "";

for (int i = 0;
     i < 1000;
     i++) {

    result += i;
}

大量拼接时效率较低。

更适合:

StringBuilder builder =
        new StringBuilder();

for (int i = 0;
     i < 1000;
     i++) {

    builder.append(i);
}

三十七、StringBuilder.append()

追加内容:

StringBuilder sb =
        new StringBuilder();

sb.append("姓名:");

sb.append("张三");

sb.append(", 年龄:");

sb.append(20);

也可以链式调用:

sb.append("姓名:")
  .append("张三")
  .append(", 年龄:")
  .append(20);

三十八、StringBuilder.insert()

在指定位置插入:

StringBuilder sb =
        new StringBuilder(
                "Java"
        );

sb.insert(
        4,
        " Web"
);

结果:

Java Web

三十九、StringBuilder.delete()

删除指定区间:

StringBuilder sb =
        new StringBuilder(
                "Hello Java"
        );

sb.delete(
        0,
        6
);

结果:

Java

同样是:

左闭右开

四十、StringBuilder.deleteCharAt()

删除某一个字符:

sb.deleteCharAt(0);

四十一、StringBuilder.replace()

替换指定区间:

StringBuilder sb =
        new StringBuilder(
                "Hello Java"
        );

sb.replace(
        6,
        10,
        "Spring"
);

结果:

Hello Spring

四十二、StringBuilder.reverse()

反转:

StringBuilder sb =
        new StringBuilder(
                "Java"
        );

sb.reverse();

System.out.println(sb);

输出:

avaJ

四十三、StringBuilder.length()

sb.length()

获取当前字符数量。


四十四、StringBuilder 和 String 互转

String → StringBuilder:

StringBuilder sb =
        new StringBuilder(
                "Java"
        );

StringBuilder → String:

String text =
        sb.toString();

四十五、StringBuffer

StringBuffer 和 StringBuilder 的功能非常相似。

例如:

StringBuffer buffer =
        new StringBuffer();

buffer.append("Java");

核心区别可以先记:

StringBuilder
通常更快
非线程安全

StringBuffer
方法带同步处理
线程安全性更高

现代普通业务代码中:

StringBuilder 使用更频繁

四十六、String、StringBuilder、StringBuffer 对比

类型 是否可变 线程安全 常见用途
String 不可变 天然较安全 普通字符串
StringBuilder 可变 否 单线程大量拼接
StringBuffer 可变 较安全 特殊多线程场景

日常可以先记:

普通字符串 → String

大量拼接 → StringBuilder

四十七、包装类

Java 有 8 种基本数据类型。

每一种基本类型都有对应包装类。

基本类型 包装类
byte Byte
short Short
int Integer
long Long
float Float
double Double
char Character
boolean Boolean

四十八、为什么需要包装类

因为很多 Java API:

只能操作对象
不能直接操作基本类型

例如后面的集合:

ArrayList<Integer>

不能写:

ArrayList<int>

所以需要:

Integer

包装 int。


四十九、装箱和拆箱

基本类型:

int number = 10;

变成包装类:

Integer value = number;

叫:

自动装箱

包装类变回基本类型:

int result = value;

叫:

自动拆箱

五十、自动装箱

以前可以显式:

Integer value =
        Integer.valueOf(10);

现在通常:

Integer value = 10;

Java 自动处理。


五十一、包装类不能忽视 null

基本类型:

int

不能为:

null

但:

Integer

可以:

Integer number = null;

如果自动拆箱:

int value = number;

会出现:

NullPointerException

这是实际开发中非常常见的问题。


五十二、Integer.parseInt()

把数字字符串转换成:

int

例如:

String text = "123";

int number =
        Integer.parseInt(text);

结果:

123

五十三、其他 parse 方法

Long.parseLong("100");

Double.parseDouble("3.14");

Float.parseFloat("3.14");

Boolean.parseBoolean("true");

五十四、NumberFormatException

如果:

Integer.parseInt("abc");

无法转成整数,

会出现:

NumberFormatException

它属于异常机制,下一章会详细学习。


五十五、Integer.valueOf()

Integer value =
        Integer.valueOf("123");

得到的是:

Integer

而:

Integer.parseInt("123")

得到的是:

int

五十六、Integer 常量

常见:

Integer.MAX_VALUE

表示:

int 最大值
Integer.MIN_VALUE

表示:

int 最小值

例如:

System.out.println(
        Integer.MAX_VALUE
);

五十七、进制转换

十进制转二进制:

Integer.toBinaryString(10);

结果:

1010

转十六进制:

Integer.toHexString(255);

结果:

ff

转八进制:

Integer.toOctalString(10);

五十八、Character 常用方法

判断是不是数字:

Character.isDigit('8');

判断是不是字母:

Character.isLetter('A');

判断大写:

Character.isUpperCase('A');

判断小写:

Character.isLowerCase('a');

转换:

Character.toUpperCase('a');

结果:

A

五十九、包装类缓存简单了解

例如:

Integer a = 100;
Integer b = 100;

System.out.println(a == b);

可能得到:

true

而:

Integer a = 200;
Integer b = 200;

== 的结果不要依赖。

原因涉及:

包装类缓存

因此包装类比较内容:

a.equals(b)

更加稳妥。

不要因为小整数测试通过,就用:

==

比较包装类业务值。


六十、Math 类

Math 提供大量数学计算方法。

特点:

大多数方法都是 static

所以不需要:

new Math()

直接:

Math.xxx()

六十一、Math.abs()

绝对值:

Math.abs(-10)

结果:

10

六十二、Math.max() 和 Math.min()

最大值:

Math.max(10, 20)

结果:

20

最小值:

Math.min(10, 20)

六十三、Math.pow()

幂运算:

Math.pow(2, 3)

结果:

8.0

返回通常是:

double

六十四、Math.sqrt()

平方根:

Math.sqrt(16)

结果:

4.0

六十五、Math.ceil()

向上取整:

Math.ceil(3.1)

结果:

4.0

六十六、Math.floor()

向下取整:

Math.floor(3.9)

结果:

3.0

六十七、Math.round()

四舍五入:

Math.round(3.6)

结果:

4

例如:

Math.round(3.4)

结果:

3

注意不同数值类型对应返回类型略有区别。


六十八、Math.random()

生成:

0.0 <= 随机数 < 1.0

例如:

double random =
        Math.random();

六十九、生成指定范围随机整数

生成:

0 ~ 9
int number =
        (int) (
                Math.random()
                * 10
        );

生成:

1 ~ 10
int number =
        (int) (
                Math.random()
                * 10
        ) + 1;

七十、Random 类

除了:

Math.random()

Java 还提供:

java.util.Random

例如:

import java.util.Random;

Random random =
        new Random();

七十一、Random.nextInt()

int number =
        random.nextInt(10);

生成范围:

0 ~ 9

七十二、Random 生成 1 ~ 100

int number =
        random.nextInt(100)
        + 1;

范围:

1 ~ 100

七十三、Random.nextBoolean()

boolean value =
        random.nextBoolean();

随机产生:

true
false

七十四、Random.nextDouble()

double value =
        random.nextDouble();

七十五、ThreadLocalRandom 简单了解

在并发程序中经常看到:

ThreadLocalRandom

例如:

import java.util.concurrent
        .ThreadLocalRandom;

int number =
        ThreadLocalRandom
                .current()
                .nextInt(
                        1,
                        101
                );

范围:

1 ~ 100

后面学习多线程时再深入。


七十六、BigDecimal

金额计算中一个非常重要的类:

java.math.BigDecimal

为什么需要它?

看:

System.out.println(
        0.1 + 0.2
);

结果可能是:

0.30000000000000004

这和浮点数底层表示有关。


七十七、金额为什么不推荐直接 double

例如:

double price = 0.1;

double total =
        price + 0.2;

涉及:

金额
金融
结算
高精度小数

时,精度误差可能不可接受。

因此常使用:

BigDecimal

七十八、正确创建 BigDecimal

推荐:

BigDecimal a =
        new BigDecimal("0.1");

BigDecimal b =
        new BigDecimal("0.2");

或者:

BigDecimal a =
        BigDecimal.valueOf(0.1);

不推荐直接:

new BigDecimal(0.1);

因为可能把 double 本身的精度误差带进去。


七十九、BigDecimal 加法

BigDecimal result =
        a.add(b);

八十、BigDecimal 减法

BigDecimal result =
        a.subtract(b);

八十一、BigDecimal 乘法

BigDecimal result =
        a.multiply(b);

八十二、BigDecimal 除法

BigDecimal result =
        a.divide(b);

但是某些无法整除的小数:

1 / 3

如果不指定精度,可能抛异常。

因此实际开发常写:

BigDecimal result =
        a.divide(
                b,
                2,
                RoundingMode.HALF_UP
        );

八十三、RoundingMode

需要:

import java.math.RoundingMode;

常见:

RoundingMode.HALF_UP

可以理解为常见的:

四舍五入

八十四、BigDecimal setScale()

保留小数位:

BigDecimal money =
        new BigDecimal(
                "12.345"
        );

BigDecimal result =
        money.setScale(
                2,
                RoundingMode.HALF_UP
        );

结果:

12.35

八十五、BigDecimal 比较不能只看 equals()

例如:

BigDecimal a =
        new BigDecimal("1.0");

BigDecimal b =
        new BigDecimal("1.00");

equals() 还会考虑:

scale

所以:

a.equals(b)

可能是:

false

八十六、BigDecimal compareTo()

业务金额比较通常更常用:

a.compareTo(b)

返回:

负数 → a < b

0 → a == b

正数 → a > b

例如:

if (a.compareTo(b) == 0) {

    System.out.println(
            "金额相等"
    );
}

八十七、BigDecimal 常见金额案例

BigDecimal price =
        new BigDecimal(
                "19.90"
        );

BigDecimal count =
        new BigDecimal(
                "3"
        );

BigDecimal total =
        price.multiply(count);

System.out.println(total);

结果:

59.70

八十八、System 类

System 提供很多系统级功能。

常见:

标准输入输出
获取时间
数组复制
系统属性
程序退出

八十九、System.out

平时最常用:

System.out.println();

其中:

System
类

out
静态成员

println
方法

九十、System.currentTimeMillis()

获取当前时间戳:

long time =
        System.currentTimeMillis();

单位:

毫秒

它常用于:

简单性能测试
生成时间相关值
记录时间

九十一、简单计算代码运行耗时

long start =
        System.currentTimeMillis();

for (int i = 0;
     i < 1_000_000;
     i++) {

}

long end =
        System.currentTimeMillis();

System.out.println(
        "耗时:"
                + (end - start)
                + "ms"
);

更精细的性能测试还有专门工具,不应只依赖这种方式。


九十二、System.nanoTime()

适合:

测量时间间隔

例如:

long start =
        System.nanoTime();

后面再减。

不要把它直接理解成:

当前日期时间

九十三、System.arraycopy()

数组章节已经学过:

System.arraycopy(
        source,
        sourcePos,
        target,
        targetPos,
        length
);

用于高效复制数组。


九十四、System.exit()

System.exit(0);

可以终止 JVM 进程。

参数:

0

通常表示正常退出。

一般业务开发中不要随意使用。


九十五、Objects 工具类

Java 提供:

java.util.Objects

帮助处理对象。

例如:

Objects.equals(a, b)

九十六、Objects.equals()

安全比较两个对象:

String a = null;

String b = null;

System.out.println(
        Objects.equals(a, b)
);

结果:

true

它可以很好地处理:

null

九十七、Objects.isNull() 和 nonNull()

Objects.isNull(obj);

判断:

obj == null
Objects.nonNull(obj);

判断:

obj != null

在 Stream 等场景也经常出现。


九十八、Objects.requireNonNull()

用于要求参数不能为空:

this.name =
        Objects.requireNonNull(
                name,
                "name 不能为空"
        );

如果:

name == null

会抛出异常。


九十九、Optional 简单了解

Java 8 提供:

Optional<T>

它用于表达:

一个值可能存在,也可能不存在

例如:

Optional<String> optional =
        Optional.of("Java");

一百、Optional.ofNullable()

允许传入:

null

例如:

Optional<String> optional =
        Optional.ofNullable(
                name
        );

一百零一、Optional.orElse()

如果值不存在,提供默认值:

String result =
        optional.orElse(
                "未知"
        );

一百零二、Optional.ifPresent()

如果存在就执行:

optional.ifPresent(
        value ->
                System.out.println(
                        value
                )
);

Lambda 会在后续阶段专门学习。

当前先知道 Optional 主要用于:

减少一些显式 null 判断
表达值可能为空

不要把 Optional 当成所有 null 问题的万能替代品。


一百零三、日期时间类发展

Java 日期时间 API 大致经历:

Date
Calendar
↓
Java 8 java.time

现代 Java 开发中更推荐:

java.time

常见:

LocalDate
LocalTime
LocalDateTime
Instant
Duration
Period
DateTimeFormatter

一百零四、Date 类简单了解

旧 API:

java.util.Date

例如:

Date date =
        new Date();

System.out.println(date);

仍然会在旧项目中看到。

但新代码一般优先:

java.time

一百零五、LocalDate

表示:

日期

例如:

2026-09-09

不包含具体时间。

创建当前日期:

LocalDate today =
        LocalDate.now();

需要:

import java.time.LocalDate;

一百零六、指定 LocalDate

LocalDate date =
        LocalDate.of(
                2026,
                9,
                9
        );

一百零七、LocalDate 获取年月日

date.getYear();

date.getMonthValue();

date.getDayOfMonth();

一百零八、LocalDate 加减时间

增加一天:

date.plusDays(1);

增加一个月:

date.plusMonths(1);

增加一年:

date.plusYears(1);

减少:

date.minusDays(1);

注意这些对象同样是不可变设计。

需要接收返回结果:

date =
        date.plusDays(1);

一百零九、LocalTime

表示:

时间

例如:

15:30:20

获取当前:

LocalTime time =
        LocalTime.now();

一百一十、LocalDateTime

表示:

日期 + 时间

例如:

LocalDateTime now =
        LocalDateTime.now();

常见数据库字段:

创建时间
更新时间
支付时间
登录时间

经常会用:

LocalDateTime

一百一十一、创建指定 LocalDateTime

LocalDateTime time =
        LocalDateTime.of(
                2026,
                9,
                9,
                15,
                30,
                0
        );

一百一十二、DateTimeFormatter

用于:

日期时间格式化

导入:

import java.time.format
        .DateTimeFormatter;

例如:

DateTimeFormatter formatter =
        DateTimeFormatter
                .ofPattern(
                        "yyyy-MM-dd HH:mm:ss"
                );

一百一十三、LocalDateTime 格式化成字符串

LocalDateTime now =
        LocalDateTime.now();

String text =
        now.format(
                DateTimeFormatter
                        .ofPattern(
                                "yyyy-MM-dd HH:mm:ss"
                        )
        );

输出类似:

2026-09-09 15:30:00

一百一十四、字符串解析成 LocalDate

String text =
        "2026-09-09";

LocalDate date =
        LocalDate.parse(
                text,
                DateTimeFormatter
                        .ofPattern(
                                "yyyy-MM-dd"
                        )
        );

一百一十五、字符串解析成 LocalDateTime

String text =
        "2026-09-09 15:30:00";

DateTimeFormatter formatter =
        DateTimeFormatter
                .ofPattern(
                        "yyyy-MM-dd HH:mm:ss"
                );

LocalDateTime time =
        LocalDateTime.parse(
                text,
                formatter
        );

一百一十六、日期格式中的常见字母

常见:

yyyy   年
MM     月
dd     日
HH     24 小时制小时
mm     分钟
ss     秒

例如:

yyyy-MM-dd HH:mm:ss

注意:

MM 是月

mm 是分钟

非常容易写错。


一百一十七、Period

用于计算:

日期之间的年月日差

例如:

LocalDate start =
        LocalDate.of(
                2000,
                1,
                1
        );

LocalDate end =
        LocalDate.of(
                2026,
                9,
                9
        );

Period period =
        Period.between(
                start,
                end
        );

获取:

period.getYears();
period.getMonths();
period.getDays();

一百一十八、Duration

用于表示:

时间之间的间隔

例如:

LocalDateTime start =
        LocalDateTime.now();

LocalDateTime end =
        start.plusHours(2);

Duration duration =
        Duration.between(
                start,
                end
        );

获取小时:

duration.toHours();

一百一十九、Instant

Instant 表示:

UTC 时间线上的时间点

例如:

Instant now =
        Instant.now();

它在:

服务端时间
时间戳
跨时区系统

中比较常见。

初学阶段先知道即可。


一百二十、时区 ZoneId 简单了解

不同地区有不同:

时区

例如:

ZoneId zone =
        ZoneId.of(
                "Asia/Shanghai"
        );

或者:

Asia/Tokyo

跨地区系统不能简单假设:

所有用户时间都一样

后端项目中时间设计是很重要的问题。


一百二十一、UUID

Java 常用:

java.util.UUID

生成全局唯一标识。

例如:

String id =
        UUID.randomUUID()
                .toString();

System.out.println(id);

输出类似:

550e8400-e29b-41d4-a716-446655440000

一百二十二、去掉 UUID 中的横线

String id =
        UUID.randomUUID()
                .toString()
                .replace(
                        "-",
                        ""
                );

一百二十三、UUID 常见用途

例如:

临时文件名
请求标识
业务流水辅助标识
随机 token 的组成部分

但数据库主键如何设计不能只因为“UUID 唯一”就随便决定。

主键选择需要结合:

索引
存储
分布式系统
业务规则

综合考虑。


一百二十四、正则表达式

正则表达式:

Regular Expression

用于描述:

字符串匹配规则

常见用途:

手机号格式
邮箱格式
密码规则
身份证格式
数据提取
文本替换
文本切割

一百二十五、String.matches()

简单正则判断:

String phone =
        "13812345678";

boolean result =
        phone.matches(
                "1\\d{10}"
        );

如果符合:

1 开头
后面 10 位数字

得到:

true

一百二十六、常见正则符号

\d
数字

\w
字母、数字、下划线等单词字符

\s
空白字符

.
任意字符(通常不含换行,具体模式可变)

在 Java 字符串中:

\

本身也需要转义。

所以正则:

\d

在 Java 中经常写:

"\\d"

一百二十七、数量词

*     0 次或多次

+     1 次或多次

?     0 次或 1 次

{n}   正好 n 次

{n,}  至少 n 次

{n,m} n 到 m 次

例如:

"\\d{6}"

表示:

连续 6 位数字

一百二十八、字符范围

例如:

[abc]
a、b、c 中任意一个

[a-z]
小写字母

[A-Z]
大写字母

[0-9]
数字

一百二十九、手机号基础正则

简化版本:

String regex =
        "1[3-9]\\d{9}";

使用:

boolean result =
        phone.matches(regex);

注意:

手机号规则可能随业务和运营商规则变化,不应把简单教学正则当成永久权威规则。


一百三十、用户名校验

例如要求:

4 ~ 16 位
字母、数字、下划线

可以:

String regex =
        "[A-Za-z0-9_]{4,16}";

一百三十一、Pattern 和 Matcher

复杂正则处理可以使用:

Pattern
Matcher

例如:

import java.util.regex.Pattern;
import java.util.regex.Matcher;

Pattern pattern =
        Pattern.compile(
                "\\d+"
        );

Matcher matcher =
        pattern.matcher(
                "订单1001金额299"
        );

一百三十二、Matcher.find()

查找多个匹配:

while (matcher.find()) {

    System.out.println(
            matcher.group()
    );
}

输出:

1001
299

一百三十三、正则不要滥用

有些简单判断:

str.isEmpty()
str.contains()
str.startsWith()

用普通字符串 API 更直观。

不要为了显得高级,把所有字符串操作都改成正则。

正则适合:

规则匹配复杂
需要批量提取
需要复杂替换

的情况。


一百三十四、Arrays 再补充

数组章节已经学过:

Arrays.toString()
Arrays.sort()
Arrays.copyOf()
Arrays.equals()
Arrays.fill()
Arrays.binarySearch()

这里重点记住:

Arrays 是数组常用工具类

大多数方法通过:

Arrays.xxx()

直接调用。


一百三十五、Collections 和集合工具类先了解

后面学习集合框架时会遇到:

Collections

注意:

Collection

和:

Collections

不是一个东西。

现在只需要先知道:

Arrays
主要服务数组

Collections
主要服务集合

后面专门学习。


一百三十六、Enum 枚举简单回顾

枚举本质上也是特殊的类。

例如:

public enum OrderStatus {

    PENDING,
    PAID,
    SHIPPED,
    COMPLETED
}

使用:

OrderStatus status =
        OrderStatus.PAID;

相比:

String status = "paid";

枚举可以减少:

拼写错误
非法状态值
魔法字符串

一百三十七、Enum.valueOf()

字符串转枚举:

OrderStatus status =
        OrderStatus.valueOf(
                "PAID"
        );

如果字符串不存在对应枚举值,会抛异常。


一百三十八、Enum.values()

获取所有枚举值:

for (OrderStatus status
        : OrderStatus.values()) {

    System.out.println(status);
}

一百三十九、Class 类简单了解

每个 Java 类在运行时都有对应:

Class

对象。

例如:

Class<?> clazz =
        String.class;

也可以:

student.getClass();

它是后面学习:

反射
Spring 底层
框架机制

的重要基础。

当前章节不深入。


一百四十、常用类综合案例:用户注册校验

需求:

用户名:
4 ~ 16 位字母数字下划线

密码:
至少 8 位

手机号:
简单格式校验

注册时间:
保存当前时间

用户编号:
UUID

代码:

import java.time
        .LocalDateTime;
import java.time.format
        .DateTimeFormatter;
import java.util.UUID;

public class RegisterDemo {

    public static void main(
            String[] args
    ) {

        String username =
                "java_user";

        String password =
                "12345678";

        String phone =
                "13812345678";

        boolean usernameOk =
                username.matches(
                        "[A-Za-z0-9_]{4,16}"
                );

        boolean passwordOk =
                password.length()
                        >= 8;

        boolean phoneOk =
                phone.matches(
                        "1[3-9]\\d{9}"
                );

        if (!usernameOk) {

            System.out.println(
                    "用户名格式错误"
            );

            return;
        }

        if (!passwordOk) {

            System.out.println(
                    "密码至少 8 位"
            );

            return;
        }

        if (!phoneOk) {

            System.out.println(
                    "手机号格式错误"
            );

            return;
        }

        String userId =
                UUID.randomUUID()
                        .toString()
                        .replace(
                                "-",
                                ""
                        );

        String registerTime =
                LocalDateTime
                        .now()
                        .format(
                                DateTimeFormatter
                                        .ofPattern(
                                                "yyyy-MM-dd HH:mm:ss"
                                        )
                        );

        System.out.println(
                "注册成功"
        );

        System.out.println(
                "用户编号:"
                        + userId
        );

        System.out.println(
                "注册时间:"
                        + registerTime
        );
    }
}

一百四十一、综合案例:商品结算

需求:

商品单价 19.90
购买 3 件
优惠 5.00
计算实付金额
保留两位小数
import java.math.BigDecimal;
import java.math.RoundingMode;

public class OrderDemo {

    public static void main(
            String[] args
    ) {

        BigDecimal price =
                new BigDecimal(
                        "19.90"
                );

        BigDecimal count =
                new BigDecimal(
                        "3"
                );

        BigDecimal discount =
                new BigDecimal(
                        "5.00"
                );

        BigDecimal total =
                price.multiply(count);

        BigDecimal actual =
                total.subtract(
                        discount
                );

        actual =
                actual.setScale(
                        2,
                        RoundingMode.HALF_UP
                );

        System.out.println(
                "商品总额:"
                        + total
        );

        System.out.println(
                "优惠金额:"
                        + discount
        );

        System.out.println(
                "实付金额:"
                        + actual
        );
    }
}

一百四十二、综合案例:字符串统计

需求:

统计字符串中:

大写字母数量
小写字母数量
数字数量
其他字符数量

代码:

public class StringCountDemo {

    public static void main(
            String[] args
    ) {

        String text =
                "Java2026!Spring";

        int upperCount = 0;

        int lowerCount = 0;

        int digitCount = 0;

        int otherCount = 0;

        for (int i = 0;
             i < text.length();
             i++) {

            char c =
                    text.charAt(i);

            if (Character
                    .isUpperCase(c)) {

                upperCount++;

            } else if (Character
                    .isLowerCase(c)) {

                lowerCount++;

            } else if (Character
                    .isDigit(c)) {

                digitCount++;

            } else {

                otherCount++;
            }
        }

        System.out.println(
                "大写字母:"
                        + upperCount
        );

        System.out.println(
                "小写字母:"
                        + lowerCount
        );

        System.out.println(
                "数字:"
                        + digitCount
        );

        System.out.println(
                "其他字符:"
                        + otherCount
        );
    }
}

一百四十三、综合案例:统计单词出现次数

例如:

java,spring,java,mysql,java,spring

暂时不使用集合,

只练习字符串和数组:

String text =
        "java,spring,java,mysql,java,spring";

String[] words =
        text.split(",");

int javaCount = 0;

for (String word : words) {

    if ("java".equals(word)) {

        javaCount++;
    }
}

System.out.println(
        "java 出现次数:"
                + javaCount
);

后面学习:

Map

后可以更优雅地统计所有单词次数。


一百四十四、综合案例:密码脱敏

例如手机号:

13812345678

希望显示:

138****5678

可以:

String phone =
        "13812345678";

String result =
        phone.substring(
                0,
                3
        )
        + "****"
        + phone.substring(
                7
        );

System.out.println(result);

一百四十五、身份证或姓名脱敏思路

例如姓名:

张三

可显示:

张*

例如:

String name = "张三";

String result =
        name.substring(
                0,
                1
        )
        + "*";

真实系统还需要考虑:

不同姓名长度
Unicode 字符
隐私合规
业务规则