java 语言的 安装、介绍;语法、流程控制、数组、javaBean 等知识,可以查询上上一个内容
java 语言的 String、StringBuilder、集合、对象和类 进阶、窗体 等知识,可以查阅上一个内容
API (Application Programming Interface
) 应用程序编程接口;提供了已经预装的一些类和方法
所有的类都继承自 Object
类,都继承了来自 Object
提供的类方法;

toString();
默认情况下,toString()
方法会返回对象的类名,后跟符号 @
和对象的哈希码的无符号十六进制表示;(不严谨的说是哈希处理过后的内存地址)
public class testing {
public static void main(String[] args) {
C c = new C();
// 使用打印语句打印对象名时,源码层面是默认调用该对象的 .toString() 方法
System.out.println(c);
System.out.println(c.toString()); // 默认返回 包名+类名(全类名)@哈希码
}
class C {}
效果展示

这个字符串并不一定对于每个对象的实际内容都是有意义的,因为它没有提供关于对象状态的详细信息,所以通常情况下,可以根据自己的需要重写 toString()
方法
public class testing {
public static void main(String[] args) {
C c = new C();
System.out.println(c);
System.out.println(c.toString());
}
class C {
@Override
public String toString() {
return "重写后的 toString()";
}
}
效果展示

但在 Java 类中覆盖 toString()
方法的主要目的是为对象提供一个清晰、有意义的字符串表示形式,以便于调试、日志记录和代码可读性。IDEA
对 toString();
已经考虑过,可以直接通过 IDEA
编辑器生成对应的 toString()
代码

效果展示

例如 ArrayList
类,就已经重写了 toString()
方法,实现打印呈现数组效果。如果一个类打印的不是初始地址信息,那么它大概率就是重写了该方法
import java.util.ArrayList;
public class testing {
public static void main(String[] args) {
ArrayList<String> list = new ArrayList<>();
list.add("a");
list.add("b");
list.add("c");
System.out.println(list);
}
}
效果展示

equals(Object obj
);
指示其他对象是否与此对象 “相等”。Object
类 中的 equals
方法,默认比较的是对象的内存地址
public class equalsDemo {
public static void main(String[] args) {
T t = new T("张三");
T d = new T("张三");
System.out.println(t == d); // false
// equals 底层默认原理很简单 为 return (this == obj) 效果基本同上
System.out.println(t.equals(d)); // false
}
}
class T {
String name;
public T(String name) {
this.name = name;
}
}
效果展示

查看 equals
源码不难发现,Object
的 equals
的功能只是this == obj
,似乎是 java
定了一个规则,方便子类去重写
因此,父类 equals
方法基本就是为了给子类重写,通过自身业务制作 equals
方法,以便子类定制比较规则
class Student {
String name;
int age;
public Student(String name, int age) {
this.name = name;
this.age = age;
}
@Override
// 根据自身业务重写 equals 方法
public boolean equals(Object obj) {
// 判断是否为 Student 类 (同时实例化 Student 类)
if(obj instanceof Student t){
// 进行逐个比较
return this.age == t.age && this.name.equals(t.name);
}
return false;
}
}
public class equalsDemo {
public static void main(String[] args) {
Student t = new Student("张三", 22);
Student d = new Student("张三", 22);
Student c = new Student("张三", 26);
System.out.println(t == d); // false ←比较地址
System.out.println(t.equals(d)); // true
System.out.println(t.equals(c)); // false
}
}
效果展示

当然,IDEA
也是提供了自动生成 equals
方法(右键 → 生成..),智能生成对应 equals
的比较操作
class Student {
String name;
int age;
public Student(String name, int age) {
this.name = name;
this.age = age;
}
@Override // IDEA 生成的 equals 代码
public boolean equals(Object o) {
// 判断地址是否相同
if (this == o) return true;
// getClass() 的对比是两个对象的字节码文件对比
// 例如返回值: class cn.smmcat.object.Student
// 如果字节码不同,意味着类型不相同 直接返回 false
if (o == null || getClass() != o.getClass()) return false;
// 代码能走到这说明类型相同 可做强转
Student student = (Student) o;
// 逐个成员值进行比较
return age == student.age && Objects.equals(name, student.name);
}
}
其他内容
Objects
是 Object
的子类(JDK 1.7
开始)Objects.equals()
是静态方法

它实际调用的仍然是比较的类中所编写的 equals
方法;
但它的 equals
会先进行非空判断,避免空指针异常,再进行 equals
比较。
空指针异常:null.equals(obj)
另外 Objects.isNull(Object obj)
用于判断变量是否为 null
Math
类提供了执行基本数学运算的方法,它是一个工具类(没有构造函数,所有方法被 static
修饰),具体方法查阅文档
Math.abs(Int a);
绝对值
返回该数值的 int
绝对值(转正整数)
注意:若 a
是 Integer.MIN_VALUE
(-2³¹),结果仍为负数(溢出问题)
Math.ceil(double a)
向上取整
将小数部分剔除,只要存在小数部分则整数部分 +1,返回值为 double
Math.ceil(2.3)
→3.0
Math.ceil(-2.3)
→-2.0
(注意负数方向)
Math.floor(double a)
向下取整
将小数部分剔除,只返回整数部分,返回值为 double
Math.floor(2.7)
→2.0
Math.floor(-2.7)
→-3.0
Math.round(float a)
四舍五入
对浮点数的数值进行四舍五入运算,返回整数 int
,若传入的是 double
返回 long
Math.round(double a)
返回long
(参数为double
时)。- 四舍五入规则:当小数部分为
0.5
时,向正无穷方向舍入
Math.max(int a, int b)
比较返回较大值
比较两个整数,返回它们之中最大的值,返回整数 int
Math.max
支持所有数值类型(如 double
、long
)
Math.pow(double a,
次幂运算double
b)
返回 a
的 b
次幂运算,返回值 double
Math.pow(2, 3)
→8.0
- 负数的非整数次幂可能返回
NaN
(如Math.pow(-2, 0.5)
)
Math.random()
随机小数 0-1区间
返回为 double
的随机值,范围 0.0 ≤ x < 1.0
(不含 1.0)
底层调用 Random.nextDouble()
,建议直接使用 Random
类更灵活
System
类的功能都是静态的。也是工具类,都是直接类名调用即可

exit() 说明
System.exit();
在终止虚拟机时可以传一个状态码参数,0
表示正常退出,其他值表示异常终止
currentTimeMillis() 说明
返回的值是 1970年1月1日0时0分0秒
到现在所经历的毫秒值,又叫计算机中的时间原点,是 C
语言 生日
arraycopy() 说明
通过该方法,可以拷贝数组,底层通过本地方法(Native Code)实现,性能远高于手动循环复制,但是注意拷贝的方式是浅拷贝
public class equalsDemo {
public static void main(String[] args) {
int[] a = {1, 2, 3, 4};
int[] b = {5, 6, 7, 8};
// a 数组中 1 - 2 下标的内容覆盖 b 下标 0 起始往后的位置
System.arraycopy(a, 1, b, 0, 2);
System.out.println(Arrays.toString(b)); // [2, 3, 7, 8]
}
}
BigDecimal
类 用于解决小数运算中出现不精确的问题
参数
直接传入 double
值仍然会造成精度问题,因此推荐使用 String
数值表示来传参,或者 BigDecimal.valueOf(double val)
传参

常用方法
加法:public BigDecimal add(BigDecimal b);
减法:public BigDecimal subtract(BigDecimal b);
乘法:public BigDecimal multiply(BigDecimal b);
除法:public BigDecimal divide(BigDecimal b,精确几位,舍入方式);
小数精度问题说明
受二进制储存小数的逻辑和的影响,难以直接精确计算小数部分的加减
public class equalsDemo {
public static void main(String[] args) {
System.out.println(0.1 + 0.2); // 0.30000000000000004
}
}
BigDecimal 解决方案
通过 BigDecimal
方法传入字符串数值,实现小数的精确计算
public class equalsDemo {
public static void main(String[] args) {
BigDecimal num1 = new BigDecimal("1.44");
BigDecimal num2 = new BigDecimal("1.66");
double d1 = num1.add(num2).doubleValue();
System.out.println(d1); // 3.1
}
}
通过 BigDecimal.valueOf(double a)
静态方法也能实现小数的精确计算
import java.math.BigDecimal;
public class bigDecimalDemo {
public static void main(String[] args) {
BigDecimal a = BigDecimal.valueOf(0.2);
BigDecimal b = BigDecimal.valueOf(0.1);
System.out.println(a.add(b).doubleValue()); // 加 0.3
System.out.println(a.subtract(b).doubleValue()); // 减 0.1
System.out.println(a.multiply(b).doubleValue()); // 乘 0.02
System.out.println(a.divide(b).doubleValue()); // 除 2.0
}
}
注意事项
BigDecimal
的 divide
方法可能会遇到除不尽的小数时就会抛出一个 ArithmeticException: Non-terminating decimal expansion
异常。
如果使用 divide
方法,最好添加 保留小数位 和 四舍五入 参数。
舍入方式的枚举:RoundingMode.HALF_UP
四舍五入RoundingMode.UP
进一(向上取整)RoundingMode.DOWN
截断(向下取整)
import java.math.BigDecimal;
import java.math.RoundingMode;
public class bigDecimalDemo {
public static void main(String[] args) {
BigDecimal a = BigDecimal.valueOf(0.1);
BigDecimal b = BigDecimal.valueOf(0.03);
// 参数 2:保留 4 位小数
// 参数 3:采用 四舍五入 舍入方式
System.out.println(a.divide(b, 4, RoundingMode.HALF_UP).doubleValue()); // 3.3333
}
}
BigDecimal
类操作过的对象返回值仍然是 BigDecimal
,因此不能被视为数值,也不能被 Math
操作。
这个时候需要使用到它提供的 doubleValue()
方法返回实际的 double
数值即可
import java.math.BigDecimal;
public class bigDecimalDemo {
public static void main(String[] args) {
BigDecimal a = BigDecimal.valueOf(0.1);
BigDecimal b = BigDecimal.valueOf(0.3);
// Math.abs(a.subtract(b)); 报错:类型不匹配
System.out.println(Math.abs(a.subtract(b).doubleValue())); // 0.2
}
}
将基本数据类型包装成类(引用数据类型),使之支持调用对应的类方法;但从 JDK 5
版本开始已经实现自动拆装箱

使用方式
‘Integer(int)’ 自 JDK 版本 9 起已弃用并标记为移除
包装类的使用有手动装箱和手动拆箱环节,例如 int
:
- 手动装箱:调用提供的 构造 或 静态 方法,手动将基本数据类型包装成类
int a = 100;
Integer num = new Integer(a); // 通过构造方法包装(过时 不推荐)
Integer num1 = Integer.valueOf(a); // 通过静态方法
- 手动拆箱:通过
intValue()
以int
类型返回该Integer
的值
Integer num = Integer.valueOf(100); // 通过静态方法
int num2 = num.intValue(); // 返回 int 值 -> 100
- 自动拆装箱:从
JDK5
版本开始,已经实现自动装箱/拆箱操作,无需考虑转换问题
int a = Integer.valueOf(233); // 自动拆箱
Integer b = 666; // 自动装箱
提供功能
封装成包装类的基本数据类型就有了对应包装类提供的方法,这里例如 Integer
提供的方法例如:
public static String toBinaryString(int i)
转二进制public static String toOctalString(int i)
转八进制public static String toHexString(int i)
转十六进制public static int parseInt(String s)
将 数字字符串 转为 数字
int num = 10;
String a = Integer.toBinaryString(num); // 转二进制表示 1010
String b = Integer.toOctalString(num); // 转八进制表示 12
String c = Integer.toHexString(num); // 转十六进制表示 a
int d = Integer.parseInt("1") + 4; // 转为 int 数值 并执行 数字运算 -> 5
注意事项
使用 Integer
类型变量接收整数的数据时,会自动调用 Integer.valueOf()
方法进行封装,这是自动装箱的逻辑。


但自动装箱时,如果数据范围是 -128
~ 127
之内,则使用的是缓存中存在的 Integer
对象地址,当相同传入的数据进行比较,地址相同,它们比较为 true
,
但如果数据范围是 -128
~ 127
之外,会重新创建新的对象。此时它们的对象地址不同,如果进行比较则为 false
public class bigDecimalDemo {
public static void main(String[] args) {
Integer a = 127;
Integer b = 127;
System.out.println(a == b); // true
Integer c = 129;
Integer d = 129;
System.out.println(c == d); // false
}
}
Long
等包装类也有类似这样的缓存机制
Arrays
类用于数组操作的工具类,专门用于操作数组的元素

toString()
转带数组格式的字符串
该方法重写了 Object
的 toString
方法,意为了以字符串更简洁的展示数组的元素
import java.util.Arrays;
public class bigDecimalDemo {
public static void main(String[] args) {
int[] numList = {1, 2, 3, 4, 5, 6};
// 打印 toString 返回的数组格式字符串
System.out.println(Arrays.toString(numList));
}
}
效果展示

equals(Object[] a,Object[] b)
比较两个数组内容是否相同
该方法重写了 Object
的 toString
方法,意为了比较两个数组的内容是否相同
import java.util.Arrays;
public class bigDecimalDemo {
public static void main(String[] args) {
int[] numList = {1, 2, 3, 4};
int[] anotherList = {1, 2, 3, 4};
int[] nextList = {1, 2, 4, 4};
// Arrays.equals 比较数组每个内容是否一致
System.out.println(Arrays.equals(numList, anotherList)); // true
System.out.println(Arrays.equals(numList, nextList)); // false
}
}
效果展示

binarySearch(int[] a, int val)
查找索引
使用二分搜索法去查询指定元素在数组中索引的下标位置(二分查找法:需要保证数组的元素是排好序的)
import java.util.Arrays;
public class Demo {
public static void main(String[] args) {
int[] intList = {1, 3, 5, 7};
System.out.println(Arrays.binarySearch(intList, 3)); // 1
int[] intList2 = {3, 5, 1, 7};
// 当使用 binarySearch 去查找乱序的数组中值时 会出现意料之外的结果
System.out.println(Arrays.binarySearch(intList2, 1)); // -1
}
}
sort()
对数组默认升序排序
改变数组内所有元素的位置,默认进行升序排序
public class bigDecimalDemo {
public static void main(String[] args) {
int[] intList = {3, 41, 1, 1, 24, 5, 52, 32};
Arrays.sort(intList);
System.out.println(Arrays.toString(intList)); // [1, 1, 3, 5, 24, 32, 41, 52]
}
}
【拓展】二分查找
二分查找(Binary Search)是一种在有序数组中查找特定元素的搜索算法。
搜索过程从数组的中间元素开始,如果中间元素正好是目标值,则搜索过程结束;
如果目标值大于或小于中间元素,则在数组大于或小于中间元素的那一半中查找,而不是查找整个数组。
通过每次排除一半的元素,这样可以每次都能将搜索范围减半,这就是二分查找的思想。

代码实现效果如下
public static int BinarySearch(int[] arr, int target) {
// 数组没有内容 直接返回 -1
if (arr == null || arr.length == 0) {
return -1;
}
// min 和 max 用于跟踪要搜索的数组部分的起始和结束索引
int min = 0;
int max = arr.length - 1;
// 中心点 查找的目标
int mid;
// 当 min 和 max 没有重叠时,继续搜索
while (min <= max) {
// 计算中间索引
mid = min + (max - min) / 2;
// 如果中间元素正好是目标值,则返回该元素的索引
if (arr[mid] == target) {
return mid;
}
// 如果中间元素小于目标值,则调整 min 索引来搜索数组的右半部分
if (arr[mid] < target) {
min = mid + 1;
}
// 如果中间元素大于目标值,则调整 max 索引来搜索数组的左半部分
if (arr[mid] > target) {
max = mid - 1;
}
}
// 如果循环结束还没找到目标值,则返回 -1 表示未找到
return -1;
}
调用演示
public class bigDecimalDemo {
public static void main(String[] args) {
int[] arr = {13, 23, 35, 64, 75, 96, 117}
// 二分查找
System.out.println(BinarySearch(arr, 96)); // 5
}
}
【拓展】正则表达式
本质上说 正则表达式 就是一个字符串,来验证其他字符串。规则可参考如下笔记:正则表达式



使用 .matches(String telRegex)
验证内容
public class RegexDemo {
public static void main(String[] args) {
// 手机号验证规则
String telRegex = "1[3-9]\\d{9}";
// 验证环节
System.out.println("1203QDK1334".matches(telRegex)); // false
System.out.println("17620334513".matches(telRegex)); // true
}
}
【拓展】实现内容爬取
使用 Pattern
类的 complie
静态方法去传入正则规则,再使用 Matcher
去获取符合正则要求的内容,
先使用 find
方法验证是否还存在符合要求的内容,再使用 group
抽出符合要求的内容,以此循环。
find
和 group
是实现类似迭代器的效果,当使用了 find
后,group
才能获取数据,find()
用于定位下一个匹配项,group()
依赖于 find()
的成功调用,二者结合可以像迭代器一样遍历所有匹配项
public class PatternDemo {
public static void main(String[] args) {
// 需要进行爬取的文章
String data = "腐喵学校学摸鱼,热线电话:17680444041、15911011101。" +
"邮箱:smmcat@qq.com,座机电话:010-12321022," +
"热线电话:400-111-1111;搞快报名吧~";
// 将正则表达式封装成 Pattern 对象
Pattern pattern = Pattern.compile(regex);
// 传入需要爬取的文章
Matcher matcher = pattern.matcher(data);
ArrayList<String> strList = new ArrayList<>();
// 循环查找 若无内容 find 返回 false
while (matcher.find()) {
// 提取符合规则的内容
String str = matcher.group();
strList.add(str);
}
System.out.println(strList);
}
}
效果展示

时间类分为 JDK8
之前有的,和 JDK8
新增的,内容如下:

Date 类
Date
为日期和时间类,提供了例如 getTime
和 setTime
功能

import java.util.Date;
public class DateDemo {
public static void main(String[] args) {
// 当前时间 封装成 Date对象
Date date = new Date();
System.out.println(date);
// 把时间毫秒值转换成 Date对象
Date date1 = new Date(0L);
System.out.println(date1);
// 获取时间戳
System.out.println(date.getTime());
System.out.println(date1.getTime());
// 设置毫秒值
date.setTime(10000L);
System.out.println(date.getTime());
}
}
效果展示

SimpleDateFormat 类
用于时间格式化的类,优化了时间样式的展示

SimpleDateFormat
的构造方法允许通过传入字符串指定展示日期格式,标识如下:

通过 SimpleDateFormat
类,可以将 Date
类 的对象转为自定义样式的时间字符串进行显示
import java.text.SimpleDateFormat;
import java.util.Date;
public class DateDemo {
public static void main(String[] args) {
// 当前时间 封装成 Date对象
Date date = new Date();
System.out.println(date);
// 默认展示的格式
SimpleDateFormat sdf1 = new SimpleDateFormat();
System.out.println(sdf1.format(date));
// 自定义展示的格式
SimpleDateFormat sdf2 = new SimpleDateFormat("yyyy年MM月dd日 HH:mm:ss");
System.out.println(sdf2.format(date));
}
}
效果展示

同样,也可以通过 SimpleDateFormat
类,将指定规则的时间字符串转为 Date
类 对象
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
public class DateDemo {
public static void main(String[] args) throws ParseException {
String dateStr = "2025年02月20日";
// 指定接收规则
SimpleDateFormat sdf = new SimpleDateFormat("yyyy年MM月dd日");
// 通过 parse() 方法返回 Date 对象
Date date = sdf.parse(dateStr);
// 显示时间戳
System.out.println(date.getTime());
}
}
效果展示

使用了 throws ParseException
语法用于捕获异常
Calendar 类提供了日历类的功能
获取系统此刻时间对应的日历,通过它可以单独获取、修改时间中的年、月、日、时、分、秒数据

Calendar 类的常用方法

案例演示
通过 .get(intValues)
传入对应的数值。为了方便阅读在 Calendar
类中也提供对应数值绑定的静态常量的解释
常量名 | 值 | 说明 |
---|---|---|
Calendar.YEAR | 1 | 年份字段 |
Calendar.MONTH | 2 | 月份字段(0 表示 1 月) |
Calendar.DATE | 5 | 日期字段(月中的某一天) |
Calendar.DAY_OF_MONTH | 5 | 同 Calendar.DATE |
Calendar.DAY_OF_YEAR | 6 | 年份中的某一天 |
Calendar.DAY_OF_WEEK | 7 | 星期几(1 表示星期日) |
Calendar.DAY_OF_WEEK_IN_MONTH | 8 | 当前月中的第几个星期几 |
Calendar.WEEK_OF_YEAR | 3 | 当前年份中的第几周 |
Calendar.WEEK_OF_MONTH | 4 | 当前月份中的第几周 |
Calendar.HOUR | 10 | 12 小时制的小时字段 |
Calendar.HOUR_OF_DAY | 11 | 24 小时制的小时字段 |
Calendar.MINUTE | 12 | 分钟字段 |
Calendar.SECOND | 13 | 秒字段 |
Calendar.MILLISECOND | 14 | 毫秒字段 |
import java.text.ParseException;
import java.util.Calendar;
public class TestDemo {
public static void main(String[] args) throws ParseException {
// Calendar 是抽象类 需要其子类去实现
Calendar calendar = Calendar.getInstance();
System.out.println(calendar.get(Calendar.YEAR)); // 2025 (年)
System.out.println(calendar.get(Calendar.MONTH)); // 2 (月)
System.out.println(calendar.get(Calendar.DAY_OF_MONTH)); // 5 (日)
System.out.println(calendar.get(Calendar.HOUR_OF_DAY)); // 18 (时)
System.out.println(calendar.get(Calendar.MINUTE)); // 53 (分)
System.out.println(calendar.get(Calendar.SECOND)); // 0 (秒)
}
}
通过 .set(int field,int value)
修改日历类中的某个字段或者多个字段。
import java.util.Calendar;
public class TestDemo {
public static void main(String[] args) throws ParseException {
Calendar calendar = Calendar.getInstance();
calendar.set(Calendar.YEAR, 2026); // 单个修改
calendar.set(2026, Calendar.APRIL, 12); // 修改多个(有对应规则)
System.out.println(calendar.get(Calendar.YEAR)); // 2026
}
}
set
可以传入多个数据实现自由配置

通过 .add(int field,int amount)
为某个字段 增加/减少 指定的值
public class TestDemo {
public static void main(String[] args) throws ParseException {
Calendar calendar = Calendar.getInstance();
System.out.println(calendar.get(Calendar.YEAR)); // 2025 (年)
calendar.add(Calendar.YEAR, 1); // 相当于 年的值加 1 => 2026
}
}
JDK8版本后新增功能

功能概述

区别
JDK8
版本前的时间对象例如:Date()
,当修改时间对象信息后,就会改变之前的事件对象,而JDK8
版本后的时间对象为不可变对象,当修改后都会返回一个新的时间对象,不影响当前时间对象
public static void main(String[] args) throws ParseException {
// JDK8 之前的时间对象
Date date = new Date();
System.out.println(new SimpleDateFormat().format(date)); // 2025/3/10 下午10:52
date.setTime(1000);
System.out.println(new SimpleDateFormat().format(date)); // 1970/1/1 上午8:00
// JDK8 版本之后的时间对象 返回对象接收 不影响原对象数据
LocalDateTime now = LocalDateTime.now(); // 2025-03-10T22:55:34.334938500
System.out.println(now);
LocalDateTime before = now.withYear(2008);
System.out.println(before); // 2008-03-10T22:55:34.334938500
System.out.println(now); // 2025-03-10T22:56:21.609711900
}

LocalDate 代表本地日期(年、月、日、星期)
LocalTime 代表本地时间(时、分、秒、纳秒)
LocalDateTime 代表本地日期、时间(年、月、日、星期、时、分、秒、纳秒)
想获取当前时间使用 .now()
;想获取指定时间则使用 .of(...)
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
public class TestDemo {
public static void main(String[] args) throws ParseException {
LocalTime ld = LocalTime.now();
System.out.println(ld); // 15:16:57.300794600
LocalDate lt = LocalDate.now();
System.out.println(lt); // 2025-03-13
LocalDateTime ldt = LocalDateTime.now();
System.out.println(ldt); // 2025-03-13T15:16:57.301791200
LocalDateTime ldt2 = LocalDateTime.of(2008, 8, 8, 8, 8);
System.out.println(ldt2); // 2008-08-08T08:08
// 获取当前时间信息
System.out.println(LocalDateTime.now().getMonthValue()); // 当前月(值) 3
System.out.println(LocalDateTime.now().getYear()); // 2025
System.out.println(LocalDateTime.now().getHour()); // 15
}
}
LocalDateTime
的方法是 LocalDate
和 LocalTime
的总和,以下是常用方法

LocalDateTime
也提供了写入对应时间数据的方法,但不修改原对象而是返回新对象

修改多个配置用 of
,修改单个使用 with
开头,增加用 plus
开头,减少用 minus
开头的函数
判断指定日期是否在当前对象之前可以使用 isBefore
,之后可以使用 isAfter
判断两个时间是否相同使用 equals
DateTimeFormatter 日期格式化
通过 DateTimeFormatter
类,对时间类的内容进行格式化和解析
// 格式化
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy年M月d日");
System.out.println(formatter.format(LocalDate.now())); // 2025年3月14日
// 解析
String time = "2025年3月14日";
LocalDate parse = LocalDate.parse(time,formatter);
System.out.println(parse); // 2025-03-14
Instant 时间戳
Inatant.now()
获取当前时间戳,但是默认获取的时间戳默认获取的时区是UTC
- 可以使用
Instant.ofEpochMilli(毫秒)
或者Instant.ofEpochSecond(秒)
去指定时间戳距离时间原点的时间

ZoneId 时区
of
用于指定时间类的时区,例如:Instant.now().atZone(ZoneId.of("Asia/Shanghai")).toInstant()
也可以获取系统上默认的时区:ZoneId.systemDefault()
通过 ZoneId.getAvailableZoneIds()
可以获得所有支持时区的 Set<String>
集合,长度为 600

ZonedDateTime 带时区的时间
ZonedDateTime
是 Java 8 引入的日期时间 API 中的一个类,用于表示带有时区的日期和时间。
它结合了 LocalDateTime
和 ZoneId
,能够处理不同时区的日期和时间转换。

ZonedDateTime.now()
:获取当前时区的当前时间。ZonedDateTime.now(ZoneId)
:获取指定时区的当前时间。ZonedDateTime.of(...)
:通过指定年、月、日、时、分、秒、纳秒和时区创建ZonedDateTime
。
import java.time.ZonedDateTime;
import java.time.ZoneId;
public class ZonedDateTimeDemo {
public static void main(String[] args) {
// 获取当前时区的当前时间
ZonedDateTime now = ZonedDateTime.now();
System.out.println("当前时间: " + now);
// 指定时区获取当前时间
ZonedDateTime nowInNewYork = ZonedDateTime.now(ZoneId.of("America/New_York"));
System.out.println("纽约当前时间: " + nowInNewYork);
// 通过 LocalDateTime 和 ZoneId 创建 ZonedDateTime
ZonedDateTime specificTime = ZonedDateTime.of(2023, 10, 1, 12, 0, 0, 0, ZoneId.of("Asia/Shanghai"));
System.out.println("指定时间: " + specificTime);
}
}
通过 .isAfter
和 .isBefore
也可以实现比较时间效果
isAfter(ZonedDateTime)
:判断当前时间是否在指定时间之后。isBefore(ZonedDateTime)
:判断当前时间是否在指定时间之前。isEqual(ZonedDateTime)
:判断当前时间是否与指定时间相等。
import java.time.ZonedDateTime;
public class ZonedDateTimeDemo {
public static void main(String[] args) {
ZonedDateTime now = ZonedDateTime.now();
ZonedDateTime futureTime = now.plusDays(5);
// 比较时间
if (futureTime.isAfter(now)) {
System.out.println("futureTime 在 now 之后");
}
if (now.isBefore(futureTime)) {
System.out.println("now 在 futureTime 之前");
}
if (now.isEqual(now)) {
System.out.println("now 和 now 相等");
}
}
}
Duration、Period、ChronoUnit 工具类
Duration
用于计算两个“时间”间隔(秒、纳秒)Period
用于计算两个“日期”间隔(年、月、日)ChronoUnit
用于计算两个“日期”间隔
Duration
用于表示两个时间点之间的时间差异,基于秒和纳秒。它适用于处理小时、分钟、秒和纳秒的差异
import java.time.Duration;
import java.time.LocalTime;
public class DurationDemo {
public static void main(String[] args) {
LocalTime startTime = LocalTime.of(10, 0); // 10:00
LocalTime endTime = LocalTime.of(12, 30); // 12:30
// 计算时间差
Duration duration = Duration.between(startTime, endTime);
System.out.println("时间差: " + duration);
// 获取小时、分钟、秒
System.out.println("小时: " + duration.toHours());
System.out.println("分钟: " + duration.toMinutes());
System.out.println("秒: " + duration.getSeconds());
// 增加时间
Duration addedDuration = duration.plusHours(1).plusMinutes(15);
System.out.println("增加 1 小时 15 分钟后的时间差: "
+ addedDuration
);
}
}
效果展示

Period
用于表示两个日期之间的差异,基于年、月、日。它适用于处理日期的差异。
import java.time.LocalDate;
import java.time.Period;
public class PeriodDemo {
public static void main(String[] args) {
LocalDate startDate = LocalDate.of(2020, 1, 1);
LocalDate endDate = LocalDate.of(2023, 10, 1);
// 计算日期差
Period period = Period.between(startDate, endDate);
System.out.println("日期差: " + period);
// 获取年、月、日
System.out.println("年: " + period.getYears());
System.out.println("月: " + period.getMonths());
System.out.println("日: " + period.getDays());
// 增加时间
Period addedPeriod = period.plusYears(1).plusMonths(2);
System.out.println("增加 1 年 2 个月后的日期差: " + addedPeriod);
}
}
效果演示

ChronoUnit
是一个枚举类,用于表示时间单位(如天、小时、分钟等)。它通常用于计算两个时间点之间的差异
import java.time.LocalDateTime;
import java.time.temporal.ChronoUnit;
public class ChronoUnitDemo {
public static void main(String[] args) {
LocalDateTime startDateTime = LocalDateTime.of(2023, 1, 1, 10, 0);
LocalDateTime endDateTime = LocalDateTime.of(2023, 10, 1, 12, 30);
// 计算差异
long daysBetween = ChronoUnit.DAYS.between(startDateTime, endDateTime);
long hoursBetween = ChronoUnit.HOURS.between(startDateTime, endDateTime);
long minutesBetween = ChronoUnit.MINUTES.between(startDateTime, endDateTime);
System.out.println("天数差: " + daysBetween);
System.out.println("小时数差: " + hoursBetween);
System.out.println("分钟数差: " + minutesBetween);
}
}
效果演示

递归
递归就是方法直接或者间接调用自身。递归如果没有控制好终止时会出现递归死循环,导致栈内存溢出现象
public class demo {
public static void main(String[] args) {
int result = jc(5); // 120
System.out.println(result);
}
// 计算 num 的阶乘
private static int jc(int num) {
if (num == 1) {
return 1;
} else {
return num * jc(num - 1);
}
}
}
运行原理

异常
Java 异常(Exception
)是程序运行时发生的非预期事件,它会中断正常的指令流。异常的类型在 java
里面也是类

异常分类(Deepseek提供)
类型 | 特点 | 常见示例 |
---|---|---|
Error | JVM 系统级错误,程序无法处理(通常不捕获) | OutOfMemoryError 、StackOverflowError |
Exception | 程序可处理的异常,分为两类: | |
↳ Checked | 编译时强制检查(必须处理) | IOException 、SQLException |
↳ Unchecked | 运行时异常(不强制处理,通常为逻辑错误) | NullPointerException 、ArrayIndexOutOfBoundsException |
以下是 Java 中常见异常的表格说明,包含异常名称、触发场景和典型示例:
异常名称 | 触发场景 | 示例代码 | 解决方法 |
---|---|---|---|
NullPointerException | 尝试访问或调用null 对象的成员 | String str = null; str.length(); | 添加非空检查:if(str != null) {...} |
ArrayIndexOutOfBoundsException | 数组访问越界(索引<0或≥数组长度) | int[] arr = {1,2}; System.out.println(arr[2]); | 检查索引范围:if(index >=0 && index < arr.length) |
ClassCastException | 不安全的强制类型转换 | Object obj = "hello"; Integer num = (Integer) obj; | 使用instanceof 检查:if(obj instanceof Integer) |
ArithmeticException | 算术运算错误(如除以零) | int x = 5 / 0; | 添加除数检查:if(divisor != 0) {...} |
NumberFormatException | 字符串转换为数字时格式不符 | int num = Integer.parseInt("abc"); | 捕获异常或正则校验:str.matches("-?\\d+") |
IllegalArgumentException | 方法接收到非法参数 | List.subList(-1, 3); | 方法入口参数校验 |
IllegalStateException | 对象状态不符合方法调用要求 | Iterator.next() 在hasNext()=false 时调用 | 检查对象状态:if(iterator.hasNext()) {...} |
IndexOutOfBoundsException | 集合/字符串索引越界(List , String 等) | String s = "hi"; s.charAt(2); | 同数组越界处理 |
ConcurrentModificationException | 集合在迭代时被修改(非迭代器的remove() 方法) | for(String s : list) { list.remove(s); } | 使用迭代器的remove() 或CopyOnWriteArrayList |
NoSuchElementException | 调用不存在的元素(如空Optional.get() ) | Optional.empty().get(); | 使用Optional.orElse() 等安全方法 |
UnsupportedOperationException | 调用不支持的操作(如Arrays.asList() 返回不可变列表的add() ) | Arrays.asList(1,2).add(3); | 使用可变集合:new ArrayList<>(Arrays.asList(1,2)) |
FileNotFoundException | 文件路径不存在或不可访问 | new FileInputStream("nonexist.txt"); | 检查文件路径和权限 |
IOException | I/O操作失败(通用父类) | socket.getInputStream().read() 时连接断开 | 资源清理+重试机制 |
SQLException | 数据库操作错误 | stmt.executeQuery("SELECT * FROM non_exist_table"); | 检查SQL语句+连接状态 |
ClassNotFoundException | 类加载失败(JVM找不到类文件) | Class.forName("com.example.NonExistClass"); | 检查类路径和依赖 |
NoClassDefFoundError | 编译时存在但运行时缺少类定义(与ClassNotFoundException 区别在于编译阶段) | 运行时删除了已编译依赖的jar包 | 确保运行时类路径完整 |
补充说明:
- 检查型异常(Checked):必须捕获或声明抛出(如
IOException
) - 非检查型异常(Unchecked):
RuntimeException
的子类,通常由编程错误导致 - Error:系统级错误(如
OutOfMemoryError
),通常不可恢复
异常处理机制
try {
// 可能抛出异常的代码
} catch (NullPointerException e) {
// 针对性处理空指针
} catch (IllegalArgumentException e) {
// 处理参数错误
} catch (Exception e) {
// 通用异常处理
logger.error("Operation failed", e);
} finally {
// 资源释放
}
方法 | 作用 |
---|---|
e.printStackTrace() | 打印异常堆栈跟踪(调试用) |
e.getMessage() | 获取异常描述信息 |
throw new Exception("msg") | 主动抛出异常 |
自定义异常
class MyException extends Exception {
public MyException(String message) {
super(message); // 调用父类构造
}
}
异常说明
- 优先处理具体异常:避免直接捕获
Exception
- 早抛出,晚捕获:在合适层级处理异常
- 避免空 catch 块:至少记录日志(如
log.error(e)
) - 资源管理:使用
try-with-resources
(Java 7+)
Java 异常是程序错误处理的标准化机制,通过 try-catch-finally
结构实现可控的流程中断和恢复,
区分检查型和非检查型异常使错误处理更灵活
编译时异常
编译时的异常是即使你语法正确,但是仍然以为你代码运行时可能存在错误所做的一个异常提示;为了程序的运行严谨,需要提供解决方案。
import java.text.SimpleDateFormat;
import java.util.Date;
public class demo {
public static void main(String[] args) {
int result = jc(5);
System.out.println(result);
SimpleDateFormat sdf = new SimpleDateFormat("yyyy年MM月dd日");
// 即使语法错误 依然提示 未处理 异常: java.text.ParseException
Date date = sdf.parse("2025年12月11日");
System.out.println(date);
}
}
import java.text.SimpleDateFormat;
import java.util.Date;
public class demo {
public static void main(String[] args) throws ParseException {
int result = jc(5);
System.out.println(result);
SimpleDateFormat sdf = new SimpleDateFormat("yyyy年MM月dd日");
Date date = sdf.parse("2025年12月11日");
System.out.println(date);
}
}
报错提示

异常的默认处理流程
- 虚拟机会在出现异常的代码那里自动的创建一个异常对象:
ArithmeticException
- 异常会从方法中出现的点这里抛出给调用者,调用者最终抛出给
JVM
虚拟机 - 虚拟机接收到异常对象后,先在控制台直接输出异常信息数据
- 终止 Java 程序的运行
如果异常捕获抓到错误后,将直接结束后续的传递。使程序继续往下执行
public static void main(String[] args) {
try{
// 可能报错的代码
}catch (Exception e){
// Exception 父类实现多态 可以捕获更多错误
// 捕获后的代码
}
}
throws 抛出异常
throws
是 Java 中用于 声明方法可能抛出的异常 的关键字,它告诉调用者该方法可能会抛出哪些异常,以便调用者进行相应的处理。
用途 | 说明 |
---|---|
声明方法可能抛出的异常 | 方法内部不直接处理异常,而是由调用者处理 |
强制调用者处理异常 | 适用于 Checked Exception (如 IOException 、SQLException ) |
提高代码可读性 | 明确方法可能抛出的异常类型,便于维护 |
throws
的基本语法
返回类型 方法名(参数列表) throws 异常类型1, 异常类型2, ... {
// 方法体(可能抛出异常)
}
示例
```java
public void readFile(String filePath) throws FileNotFoundException, IOException {
FileInputStream fis = new FileInputStream(filePath); // 可能抛出 FileNotFoundException
// 其他 IO 操作可能抛出 IOException
}
throws
与 try-catch
的区别
方式 | 适用场景 | 特点 |
---|---|---|
throws | 方法内部不处理异常,交给调用者处理 | 适用于 Checked Exception |
try-catch | 方法内部自行处理异常 | 适用于 RuntimeException 或需要立即处理的异常 |
示例
// 方式1:使用 throws 让调用者处理异常
public void methodA() throws IOException {
// 可能抛出 IOException
}
// 方式2:使用 try-catch 自行处理异常
public void methodB() {
try {
// 可能抛出 IOException
} catch (IOException e) {
e.printStackTrace();
}
}
业务用途
throws
也适用于主动抛出异常的情况。如果当前代码别人调用时存在可能报错的问题,可以主动 throw
一个错误类,方便他人调用时注意
public class demo {
// 调用方可以选择继续抛出或者使用 try{}catch{} 捕获
public static void main(String[] args) throws Exception {
putAge(-12);
}
public static void putAge(int age) throws Exception {
if (age <= 0 || age > 100) {
throw new Exception("年龄传入有误,需要在 1-100 之间");
}
// 执行传参业务
// ...
System.out.println("完成");
}
}
效果展示

也可以通过 try catch
捕获异常,并使用 e.getMessage()
获取报错的消息
public class demo {
// 调用方可以选择继续抛出或者使用 try{}catch{} 捕获
public static void main(String[] args) {
try {
putAge(-12);
} catch (Exception e) {
System.out.println(e.getMessage());
}
}
public static void putAge(int age) throws Exception {
if (age <= 0 || age > 100) {
throw new Exception("年龄传入有误,需要在 1-100 之间");
}
// 执行传参业务
// ...
System.out.println("完成");
}
}
效果展示

每个异常的类都不同,因此 catch
只会捕获对应支持的异常的值,当有多个异常需要捕获需要注意最大的异常排后
public static void main(String[] args) {
try {
int x = 5 / 0;
putAge(-12);
} catch (ArithmeticException e) {
System.out.println("运算异常");
} catch (Exception e) {
System.out.println(e.getMessage());
}
}
另外,还有 RuntimeException
异常,属于运行时异常。在运行时可能发生的错误,无需声明 throws
public class demo {
public static void main(String[] args) {
try {
putAge(-12);
} catch (RuntimeException e) {
System.out.println(e.getMessage());
}
}
public static void putAge(int age) {
if (age <= 0 || age > 100) {
throw new RuntimeException("传入的值范围不对");
}
// 执行传参业务
// ...
System.out.println("完成");
}
}
效果展示

除了 ArrayList
以外,还有很多不同种类的集合。它们可以如下分类(实现了 Collection
接口的、实现了 Map
接口的)

Collection
接口)双列集合(实现 Map
接口)单列集合:
Collection
接口又分为List
接口(ArrayList
、LinkedList
) 和Set
接口(TreeMap
、HashMap
、LinkedHashMap
)List
接口的特点是 存取有序、有索引、可以存储重复的Set
接口的特点是 存储无序、没有索引、不可以存储重复的
Collection
通用接口方法

通过多态实现调用拥有方法,发现 Set
和 List
接口的不同
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
public class test1 {
public static void main(String[] args) {
// 以多态的形式创建集合对象 调用集合中的共有方法
Collection<String> a = new ArrayList<>();
boolean b1 = a.add("a");
boolean b2 = a.add("a");
boolean b3 = a.add("a");
System.out.println(b1); // true
System.out.println(b2); // true
System.out.println(b3); // true
System.out.println(a); // ["a","b","c"]
Collection<String> b = new HashSet<>();
boolean b4 = b.add("a");
boolean b5 = b.add("a");
boolean b6 = b.add("a");
System.out.println(b4); // true
System.out.println(b5); // false
System.out.println(b6); // false
System.out.println(b); // ["a"]
}
}
通过调用 `Collection