06Java 异常机制与常用类

✨博客主页: https://blog.csdn.net/m0_63815035?type=blog

💗《博客内容》:大数据、AI开发、Java、测试开发、Python、Android、Go、Node、Android前端小程序等相关领域知识
📢博客专栏: https://blog.csdn.net/m0_63815035/category_11954877.html
📢欢迎点赞 👍 收藏 ⭐留言 📝
📢本文为学习笔记资料,如有侵权,请联系我删除,疏漏之处还请指正🙉
📢大厦之成,非一木之材也;大海之阔,非一流之归也✨

目录

    • [第一部分:异常机制(Exception Handling)](#第一部分:异常机制(Exception Handling))
      • [1. 异常的概念与必要性](#1. 异常的概念与必要性)
      • [2. 异常的层次结构](#2. 异常的层次结构)
      • [3. 异常的产生与传播](#3. 异常的产生与传播)
      • [4. 异常处理方式](#4. 异常处理方式)
        • 方式一:try-catch-finally
        • [方式二:throws 声明抛出](#方式二:throws 声明抛出)
        • [throw 关键字(手动抛出)](#throw 关键字(手动抛出))
      • [5. finally 与 return 的纠缠(经典面试题)](#5. finally 与 return 的纠缠(经典面试题))
      • [6. try-with-resources(JDK7+)](#6. try-with-resources(JDK7+))
      • [7. 异常链(Exception Chaining)](#7. 异常链(Exception Chaining))
      • [8. 自定义异常](#8. 自定义异常)
      • [9. 常见运行时异常及避免方法](#9. 常见运行时异常及避免方法)
      • [10. 异常处理最佳实践](#10. 异常处理最佳实践)
    • 第二部分:常用类详解
      • [1. Object 类(所有类的根)](#1. Object 类(所有类的根))
        • [1.1 toString()](#1.1 toString())
        • [1.2 equals()](#1.2 equals())
        • [1.3 hashCode()](#1.3 hashCode())
        • [1.4 clone() 与 Cloneable 接口](#1.4 clone() 与 Cloneable 接口)
        • [1.5 getClass() 和 finalize()](#1.5 getClass() 和 finalize())
      • [2. 包装类(Wrapper Class)](#2. 包装类(Wrapper Class))
        • [2.1 基本对应关系](#2.1 基本对应关系)
        • [2.2 构造与转换(以 Integer 为例)](#2.2 构造与转换(以 Integer 为例))
        • [2.3 自动装箱与拆箱(编译器语法糖)](#2.3 自动装箱与拆箱(编译器语法糖))
        • [2.4 缓存池](#2.4 缓存池)
        • [2.5 常用常量与方法](#2.5 常用常量与方法)
      • [3. 时间处理类](#3. 时间处理类)
        • [3.1 旧版 Date & Calendar(线程不安全,不推荐)](#3.1 旧版 Date & Calendar(线程不安全,不推荐))
        • [3.2 Java 8 新时间 API(推荐)](#3.2 Java 8 新时间 API(推荐))
      • [4. 数组(Array)](#4. 数组(Array))
        • [4.1 内存结构](#4.1 内存结构)
        • [4.2 创建与初始化](#4.2 创建与初始化)
        • [4.3 多维数组(非规则数组)](#4.3 多维数组(非规则数组))
        • [4.4 Arrays 工具类(java.util.Arrays)](#4.4 Arrays 工具类(java.util.Arrays))
        • [4.5 数组复制与扩容](#4.5 数组复制与扩容)
      • [5. 字符串(String)](#5. 字符串(String))
        • [5.1 String 的不可变性](#5.1 String 的不可变性)
        • [5.2 字符串常量池](#5.2 字符串常量池)
        • [5.3 常用方法](#5.3 常用方法)
        • [5.4 StringBuilder / StringBuffer](#5.4 StringBuilder / StringBuffer)
      • [6. Math 类](#6. Math 类)
      • [7. File 类(java.io.File)](#7. File 类(java.io.File))
        • [7.1 构造](#7.1 构造)
        • [7.2 常用方法](#7.2 常用方法)
        • [7.3 递归遍历目录](#7.3 递归遍历目录)
      • [8. 枚举(Enum)](#8. 枚举(Enum))
        • [8.1 基本用法](#8.1 基本用法)
        • [8.2 枚举的本质](#8.2 枚举的本质)
        • [8.3 带字段和构造器的枚举](#8.3 带字段和构造器的枚举)
        • [8.4 枚举实现接口](#8.4 枚举实现接口)
        • [8.5 枚举的单例模式](#8.5 枚举的单例模式)
        • [8.6 EnumSet 和 EnumMap(性能高效)](#8.6 EnumSet 和 EnumMap(性能高效))
    • 总结

本章主要涵盖 Java 异常处理的完整机制,以及日常开发中最常用的类:Object、包装类、时间处理、数组、字符串、Math、File、枚举。感谢大家观看


第一部分:异常机制(Exception Handling)

1. 异常的概念与必要性

异常(Exception)是指程序在运行时发生的非正常情况,如除零、数组越界、文件找不到、网络中断等。如果没有异常处理,程序会直接崩溃。异常机制让程序在遇到问题时能够:

  • 捕获 异常并做出合理响应(如提示用户、记录日志)
  • 清理 资源(关闭文件、数据库连接)
  • 平稳退出 或尝试其他路径

2. 异常的层次结构

Java 中所有异常都继承自 java.lang.Throwable 类。

复制代码
Throwable
├── Error               // 严重错误,程序无法处理
│   ├── OutOfMemoryError
│   ├── StackOverflowError
│   └── ...
└── Exception           // 需要处理的异常
    ├── RuntimeException // 运行时异常(非受检异常)
    │   ├── NullPointerException
    │   ├── ArithmeticException
    │   ├── ArrayIndexOutOfBoundsException
    │   ├── ClassCastException
    │   ├── IllegalArgumentException
    │   └── ...
    └── 其他 Exception    // 受检异常(Checked Exception)
        ├── IOException
        ├── SQLException
        ├── ParseException
        └── ...

关键区别

  • Error :JVM 内部错误、资源耗尽等,应用程序无法恢复,通常不处理(例如 OutOfMemoryError 你 catch 了也救不回来)。
  • RuntimeException:编译器不强制处理,通常由编程错误引起(如空指针、除数零)。应当通过改进代码逻辑避免,而不是用 try-catch 掩盖。
  • Checked Exception:编译器强制要求处理(要么 try-catch,要么 throws),代表外部不可控因素(文件不存在、网络故障)。

3. 异常的产生与传播

java 复制代码
public class Demo {
    public static void main(String[] args) {
        method1();
    }
    static void method1() {
        method2();
    }
    static void method2() {
        int a = 10 / 0;   // 这里产生 ArithmeticException
    }
}

过程

  1. method2 执行到 10/0 时,JVM 检测到除零错误,创建一个 ArithmeticException 对象。
  2. 当前方法没有 catch 该异常,异常对象被抛给调用者 method1
  3. method1 也没有处理,继续抛给 main
  4. main 也没有处理,最终抛给 JVM,JVM 打印异常栈并终止程序。

4. 异常处理方式

方式一:try-catch-finally
java 复制代码
try {
    // 可能抛出异常的代码块
} catch (SomeException e) {
    // 处理该异常
} catch (AnotherException e) {
    // 可以有多个 catch
} finally {
    // 无论是否发生异常都会执行(除了 System.exit())
}

详细规则

  • try 块:一旦发生异常,后面的代码立即停止,跳转到对应的 catch。
  • catch 块 :可以有多个,但最多只有一个会被执行 。顺序必须从子类到父类(否则子类永远没机会执行,编译错误)。
  • finally 块 :总是执行,适合释放资源(关闭文件、socket、数据库连接)。唯一不执行的情况:在 try 或 catch 中调用了 System.exit()
  • try 可以没有 catch,但必须有 finally(即 try-finally 结构,用于保证资源释放,但异常会向上抛)。
java 复制代码
// try-finally 示例
InputStream is = null;
try {
    is = new FileInputStream("test.txt");
    // 读取操作
} finally {
    if (is != null) is.close();  // 确保关闭
}
// 如果发生异常,finally 执行后异常继续向上抛
方式二:throws 声明抛出

在方法签名上声明 throws,表示本方法不处理异常,交给调用者处理。

java 复制代码
public static void readFile() throws IOException {
    FileInputStream fis = new FileInputStream("test.txt");
    // ...
}

// 调用者必须处理
public static void main(String[] args) {
    try {
        readFile();
    } catch (IOException e) {
        e.printStackTrace();
    }
}

注意 :重写方法时,子类方法抛出的异常不能比父类方法抛出的异常更宽泛(即不能抛出父类未声明的受检异常)。

throw 关键字(手动抛出)

可以在代码中主动抛出异常对象。

java 复制代码
if (age < 0 || age > 150) {
    throw new IllegalArgumentException("年龄必须在0~150之间");
}

5. finally 与 return 的纠缠(经典面试题)

java 复制代码
public static int test() {
    int x = 1;
    try {
        return x;   // ① 暂存返回值 1
    } finally {
        x = 2;      // ② 修改局部变量
    }
}
// 结果返回 1,而不是 2

解释

  • return x 不会立即返回,而是先计算表达式值(1)并暂存。
  • 执行 finally 块。
  • 最后返回暂存的值(1)。

特殊情况 :如果 finally 中也含有 return,则会覆盖暂存值。

java 复制代码
public static int test() {
    try {
        return 1;
    } finally {
        return 2;   // 会覆盖
    }
}
// 返回 2

总结 :避免在 finally 中使用 return,否则会吞掉 trycatch 中的异常。

6. try-with-resources(JDK7+)

用于自动关闭实现了 AutoCloseable 接口的资源(如流、数据库连接)。

java 复制代码
try (FileInputStream fis = new FileInputStream("test.txt");
     BufferedInputStream bis = new BufferedInputStream(fis)) {
    // 使用资源
} catch (IOException e) {
    e.printStackTrace();
}
// 无需显式 close,自动调用

等价于 try-finally 写法,更简洁安全。

7. 异常链(Exception Chaining)

在捕获一个异常后,抛出另一个异常,同时保留原始异常信息。

java 复制代码
try {
    // 底层操作
} catch (SQLException e) {
    throw new ServiceException("业务异常", e);  // 第二个参数是 cause
}

可通过 e.getCause() 获取原始异常。

8. 自定义异常

何时自定义 :当 JDK 内置异常不足以表达业务语义时(如 InsufficientBalanceExceptionUserNotFoundException)。

步骤

java 复制代码
// 受检异常
public class MyCheckedException extends Exception {
    public MyCheckedException() {}
    public MyCheckedException(String message) {
        super(message);
    }
    public MyCheckedException(String message, Throwable cause) {
        super(message, cause);
    }
}

// 非受检异常(常用)
public class MyRuntimeException extends RuntimeException {
    public MyRuntimeException(String message) {
        super(message);
    }
}

建议

  • 如果是业务逻辑错误,通常继承 RuntimeException,避免强迫调用者处理。
  • 如果是外部因素可恢复的(如重试),可以继承 Exception

9. 常见运行时异常及避免方法

异常 常见原因 避免方法
NullPointerException 调用 null 对象的方法/属性 调用前判空,或用 Optional
ArrayIndexOutOfBoundsException 访问数组越界 确保索引在 0~length-1
ClassCastException 类型转换失败 instanceof 检查
ArithmeticException 整数除零 检查分母不为0
NumberFormatException 字符串转数字格式错误 用正则或 try-catch
IllegalArgumentException 参数不合法 方法入口做参数校验

10. 异常处理最佳实践

  1. 不要吞异常catch 后什么都不做(空 catch)极其糟糕,会掩盖错误。
  2. 日志记录 :使用 logger.error("xxx", e) 打印堆栈。
  3. 尽早抛出,晚点捕获:底层抛出具体异常,上层统一处理。
  4. 不要用异常控制正常流程:异常性能差,用 if-else 代替。
  5. 关闭资源:使用 try-with-resources 或 finally。
  6. 抛出的异常要合适 :不要抛出 Exception,尽量具体(如 IOException)。

第二部分:常用类详解

1. Object 类(所有类的根)

1.1 toString()

默认返回 类名@哈希码,一般需要重写。

java 复制代码
@Override
public String toString() {
    return "Person{name='" + name + "', age=" + age + "}";
}

自动调用:System.out.println(obj) 实际调用 obj.toString()

1.2 equals()

默认比较内存地址(==)。需要比较内容时重写。

重写契约

  • 自反性:x.equals(x) 为 true
  • 对称性:x.equals(y)y.equals(x) 结果相同
  • 传递性
  • 一致性:多次调用结果不变
  • null 比较返回 false
java 复制代码
@Override
public boolean equals(Object obj) {
    if (this == obj) return true;
    if (obj == null || getClass() != obj.getClass()) return false;
    Person p = (Person) obj;
    return age == p.age && Objects.equals(name, p.name);
}
1.3 hashCode()

必须与 equals 保持一致:如果 equals 相等,hashCode 必须相等。反之不要求。

java 复制代码
@Override
public int hashCode() {
    return Objects.hash(name, age);
}

作用 :用于哈希集合(HashMapHashSet)的快速查找。

1.4 clone() 与 Cloneable 接口

Cloneable 是个标记接口(没有方法),指示 Object.clone() 可以合法复制对象。

浅拷贝(默认):

java 复制代码
class Student implements Cloneable {
    String name;
    int[] scores;
    @Override
    public Object clone() throws CloneNotSupportedException {
        return super.clone();  // 浅拷贝:scores 数组引用相同
    }
}

深拷贝:手动复制引用类型字段。

java 复制代码
@Override
public Object clone() throws CloneNotSupportedException {
    Student s = (Student) super.clone();
    s.scores = this.scores.clone();  // 数组是引用类型,需要单独克隆
    return s;
}

注意 :克隆时如果字段是自定义对象,该对象也需实现 Cloneable

1.5 getClass() 和 finalize()
  • getClass():返回运行时类对象(Class 实例),用于反射。
  • finalize():垃圾回收前调用,已废弃(从 Java 9 开始)。不推荐使用。

2. 包装类(Wrapper Class)

2.1 基本对应关系
基本类型 包装类
byte Byte
short Short
int Integer
long Long
float Float
double Double
char Character
boolean Boolean
2.2 构造与转换(以 Integer 为例)
java 复制代码
// 构造(JDK9 后标记为过时,推荐 valueOf)
Integer i1 = new Integer(10);
Integer i2 = Integer.valueOf(10);   // 推荐,有缓存

// 字符串转 Integer
Integer i3 = Integer.valueOf("123");
int i4 = Integer.parseInt("123");    // 返回基本类型

// 包装类转基本类型
int val = i1.intValue();

// 字符串转基本类型
int i5 = Integer.parseInt("456");
2.3 自动装箱与拆箱(编译器语法糖)
java 复制代码
Integer a = 100;        // 实际是 Integer.valueOf(100)
int b = a;              // 实际是 a.intValue()

陷阱

java 复制代码
Integer n = null;
int m = n;   // NullPointerException,因为拆箱调用 n.intValue()
2.4 缓存池
  • Integer 默认缓存 -128127valueOf() 在此范围内返回缓存对象,否则 new Integer
  • ByteShortLong 也缓存 -128~127
  • Character 缓存 0~127
  • Boolean 缓存 TRUEFALSE
java 复制代码
Integer x = 127;
Integer y = 127;
System.out.println(x == y);   // true(缓存)

Integer m = 128;
Integer n = 128;
System.out.println(m == n);   // false(超出范围,新对象)

// 解决方案:用 equals 比较
System.out.println(m.equals(n)); // true
2.5 常用常量与方法
java 复制代码
System.out.println(Integer.MAX_VALUE);  // 2147483647
System.out.println(Integer.MIN_VALUE);  // -2147483648
System.out.println(Integer.SIZE);       // 32(位)
System.out.println(Integer.toBinaryString(10)); // "1010"

3. 时间处理类

3.1 旧版 Date & Calendar(线程不安全,不推荐)
java 复制代码
Date date = new Date();                     // 当前时间
long time = date.getTime();                 // 毫秒数
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String str = sdf.format(date);
Date parsed = sdf.parse("2020-01-01 12:00:00"); // 可能抛 ParseException

问题SimpleDateFormat 不是线程安全的,多线程共用需要加锁或使用 ThreadLocal

3.2 Java 8 新时间 API(推荐)

位于 java.time 包,不可变、线程安全。

核心类

  • LocalDate:日期(年-月-日)
  • LocalTime:时间(时:分:秒.纳秒)
  • LocalDateTime:日期+时间
  • ZonedDateTime:带时区的日期时间
  • Instant:时间戳(秒/纳秒)
  • Duration:时间间隔(秒、纳秒)
  • Period:日期间隔(年、月、日)
  • DateTimeFormatter:格式化器
java 复制代码
// 获取当前时间
LocalDate today = LocalDate.now();
LocalTime nowTime = LocalTime.now();
LocalDateTime now = LocalDateTime.now();

// 指定日期
LocalDate birthday = LocalDate.of(1999, 3, 15);
LocalDateTime dt = LocalDateTime.of(2024, 12, 31, 23, 59, 59);

// 解析与格式化
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
String formatted = now.format(formatter);
LocalDateTime parsed = LocalDateTime.parse("2025-01-01 10:20:30", formatter);

// 日期运算
LocalDate nextWeek = today.plusWeeks(1);
LocalDate twoMonthsAgo = today.minusMonths(2);
LocalDate nextBirthday = birthday.withYear(today.getYear());
if (nextBirthday.isBefore(today)) {
    nextBirthday = nextBirthday.plusYears(1);
}

// 时间差
Period period = Period.between(birthday, today);
System.out.println(period.getYears() + "年" + period.getMonths() + "月");

long days = ChronoUnit.DAYS.between(birthday, today);

// Instant 时间戳
Instant nowInstant = Instant.now();        // UTC 时间
long epochSecond = nowInstant.getEpochSecond();
long nano = nowInstant.getNano();

// Duration
Duration d = Duration.between(LocalTime.of(9,0), LocalTime.of(17,30));
System.out.println(d.toHours());   // 8

4. 数组(Array)

4.1 内存结构
java 复制代码
int[] arr = new int[3];
  • arr 在栈中存储引用,指向堆中一块连续内存区域。
  • 每个元素有默认初始值(0、0.0、false、\u0000、null)。
  • 引用类型数组存的是对象的引用,对象本身在堆中的其他位置。
4.2 创建与初始化
java 复制代码
// 静态初始化
int[] a = {1,2,3};
int[] b = new int[]{4,5,6};

// 动态初始化
int[] c = new int[10];      // 元素默认0
String[] d = new String[5]; // 元素默认null
4.3 多维数组(非规则数组)
java 复制代码
int[][] matrix = new int[3][4];          // 3行4列
int[][] jagged = new int[3][];
jagged[0] = new int[2];
jagged[1] = new int[4];
jagged[2] = new int[1];

int[][] arr = {{1,2},{3,4,5},{6}};
4.4 Arrays 工具类(java.util.Arrays)
java 复制代码
// 排序
int[] arr = {3,1,4,1,5,9};
Arrays.sort(arr);                    // 升序
Arrays.parallelSort(arr);            // 并发排序(大数据量)
// 二分查找(必须先排序)
int idx = Arrays.binarySearch(arr, 4);

// 填充
int[] fillArr = new int[10];
Arrays.fill(fillArr, 5);             // 全填充5
Arrays.fill(fillArr, 2, 5, 8);       // 索引2~4填充8

// 复制
int[] copy = Arrays.copyOf(arr, arr.length);
int[] rangeCopy = Arrays.copyOfRange(arr, 1, 4);

// 比较
boolean eq = Arrays.equals(arr, copy);
boolean deepEq = Arrays.deepEquals(matrix1, matrix2); // 多维

// 转字符串
System.out.println(Arrays.toString(arr));
System.out.println(Arrays.deepToString(matrix));

// 转换为 List(不可修改大小)
List<Integer> list = Arrays.asList(1,2,3);
// 注意:返回的是视图,不能 add/remove,但可以 set
4.5 数组复制与扩容
java 复制代码
// 手动扩容
int[] old = {1,2,3};
int[] newArr = new int[old.length * 2];
System.arraycopy(old, 0, newArr, 0, old.length);

5. 字符串(String)

5.1 String 的不可变性
  • String 内部使用 final char[](Java 9+ 改为 byte[])存储,且数组不对外暴露。
  • 每次修改(如 concatreplacesubstring)都会创建新的 String 对象。
java 复制代码
String s = "hello";
s = s + " world";   // 实际创建新对象,原 "hello" 变成垃圾
5.2 字符串常量池
  • 字面量 "abc" 存储在常量池(堆中,JDK7+)。
  • new String("abc") 会在堆中创建新对象,同时常量池中如果不存在也会创建。
  • intern() 方法:如果常量池中存在相等字符串,返回常量池引用;否则将当前字符串放入常量池并返回引用。
java 复制代码
String s1 = "java";
String s2 = new String("java");
System.out.println(s1 == s2);               // false
System.out.println(s1 == s2.intern());      // true

JDK 版本差异

  • JDK6:常量池在 PermGen 区域,intern() 复制字符串到永久代。
  • JDK7+:常量池移到堆,intern() 只存储引用,不再复制。
5.3 常用方法
java 复制代码
String str = " Hello World ";

// 长度
int len = str.length();

// 取字符
char ch = str.charAt(6);

// 比较
boolean eq = str.equals("hello world");          // 区分大小写
boolean eqIgnore = str.equalsIgnoreCase("hello world");
int cmp = str.compareTo("Hello");                 // 字典序

// 查找
int idx = str.indexOf('o');          // 第一个出现位置
int lastIdx = str.lastIndexOf('o');
boolean contains = str.contains("World");

// 替换
String r1 = str.replace('o', 'a');
String r2 = str.replaceAll("\\s+", "");  // 正则

// 截取
String sub = str.substring(6, 11);       // [6,11)

// 分割
String[] parts = str.split("\\s+");      // 按空白分割

// 去首尾空白
String trimmed = str.trim();

// 大小写转换
String upper = str.toUpperCase();
String lower = str.toLowerCase();

// 判断前后缀
boolean starts = str.startsWith(" He");
boolean ends = str.endsWith("ld ");

// 字符串连接
String joined = String.join("-", "a", "b", "c");  // "a-b-c"

// 格式化
String fmt = String.format("姓名:%s,年龄:%d", "张三", 25);

// 转字符数组
char[] chars = str.toCharArray();

// 字符串和基本类型的转换
String numStr = String.valueOf(123);
int num = Integer.parseInt("123");
5.4 StringBuilder / StringBuffer
  • StringBuilder(非线程安全,速度快)
  • StringBuffer(线程安全,方法有 synchronized,速度慢)

常用方法

java 复制代码
StringBuilder sb = new StringBuilder();          // 默认容量16
sb.append("hello");
sb.append(' ');
sb.append("world");
sb.insert(5, ",");
sb.delete(5, 6);
sb.replace(0, 5, "HELLO");
sb.reverse();
String result = sb.toString();

性能建议 :在循环内拼接大量字符串时,显式使用 StringBuilder,避免使用 +,因为 + 在循环内会产生大量临时对象。

6. Math 类

所有方法都是 static,主要用于数学运算。

java 复制代码
// 基本
Math.abs(-10);          // 10
Math.max(10,20);        // 20
Math.min(10,20);        // 10
Math.pow(2,3);          // 8.0
Math.sqrt(9);           // 3.0

// 取整
Math.ceil(3.2);         // 4.0 向上取整
Math.floor(3.9);        // 3.0 向下取整
Math.round(3.5);        // 4 四舍五入(返回 long)
Math.round(3.4);        // 3

// 随机数 [0.0, 1.0)
double r = Math.random();
int dice = (int)(Math.random() * 6) + 1;   // 1~6

// 三角函数、对数等
Math.sin(Math.PI/2);
Math.log(10);
Math.exp(1);

7. File 类(java.io.File)

代表文件或目录的路径,并不代表文件内容。

7.1 构造
java 复制代码
File f1 = new File("D:/test/a.txt");
File f2 = new File("D:/test", "a.txt");
File parent = new File("D:/test");
File f3 = new File(parent, "a.txt");

路径分隔符File.separator 跨平台(Windows 是 \,Linux 是 /),建议使用。

7.2 常用方法
java 复制代码
File f = new File("D:/test/a.txt");

// 判断
f.exists();
f.isFile();
f.isDirectory();
f.isHidden();
f.canRead();
f.canWrite();

// 获取信息
f.getName();          // "a.txt"
f.getPath();          // 构造时的路径
f.getAbsolutePath();  // 绝对路径
f.length();           // 字节数
f.lastModified();     // 最后修改时间(毫秒)

// 创建删除
f.createNewFile();            // 创建新文件,返回 boolean
f.mkdir();                    // 创建单级目录
f.mkdirs();                   // 创建多级目录
f.delete();                   // 删除文件或空目录
f.deleteOnExit();             // JVM 退出时删除

// 目录操作
File dir = new File("D:/test");
String[] names = dir.list();               // 文件名数组
File[] files = dir.listFiles();            // File 对象数组
File[] mp3s = dir.listFiles((d, name) -> name.endsWith(".mp3"));
7.3 递归遍历目录
java 复制代码
public static void listAll(File dir) {
    if (dir == null || !dir.exists()) return;
    if (dir.isFile()) {
        System.out.println(dir.getAbsolutePath());
    } else {
        File[] subs = dir.listFiles();
        if (subs != null) {
            for (File sub : subs) {
                listAll(sub);
            }
        }
    }
}

8. 枚举(Enum)

8.1 基本用法
java 复制代码
public enum Season {
    SPRING, SUMMER, AUTUMN, WINTER
}

每个枚举值都是 Season 类的实例,且是唯一的单例。

8.2 枚举的本质
  • 隐式继承 java.lang.Enum 类,因此不能继承其他类,但可以实现接口。
  • 枚举值实际上是 public static final 常量。
  • 编译器会自动生成 values()valueOf(String) 方法。
java 复制代码
Season s = Season.SPRING;
System.out.println(s.name());        // "SPRING"
System.out.println(s.ordinal());     // 0(声明顺序)
System.out.println(s.toString());    // "SPRING"(可重写)
8.3 带字段和构造器的枚举
java 复制代码
public enum Status {
    SUCCESS(200, "成功"),
    ERROR(500, "服务器错误"),
    NOT_FOUND(404, "资源不存在");

    private int code;
    private String msg;

    Status(int code, String msg) {
        this.code = code;
        this.msg = msg;
    }

    public int getCode() { return code; }
    public String getMsg() { return msg; }

    public static Status fromCode(int code) {
        for (Status s : values()) {
            if (s.code == code) return s;
        }
        return null;
    }
}
8.4 枚举实现接口
java 复制代码
interface Desc {
    String getDescription();
}

enum Color implements Desc {
    RED {
        public String getDescription() { return "红色"; }
    },
    BLUE {
        public String getDescription() { return "蓝色"; }
    };
}
8.5 枚举的单例模式

利用枚举的特性(JVM 保证单例、线程安全、防止反射和序列化破坏)。

java 复制代码
public enum Singleton {
    INSTANCE;
    public void doSomething() { ... }
}
8.6 EnumSet 和 EnumMap(性能高效)
java 复制代码
EnumSet<Season> set = EnumSet.of(Season.SPRING, Season.SUMMER);
EnumMap<Season, String> map = new EnumMap<>(Season.class);
map.put(Season.SPRING, "春天");

总结

异常机制

  • 区分 Error、RuntimeException 和 Checked Exception。
  • 使用 try-catch-finally 或 throws,推荐 try-with-resources。
  • finally 中避免 return。
  • 自定义异常时根据场景选择继承 Exception 还是 RuntimeException。

常用类

  • Object 的 toString/equals/hashCode 必须配合重写。
  • 包装类注意缓存池和自动装箱的空指针风险。
  • 时间处理优先用 java.time 包。
  • 数组工具类 Arrays 提供丰富操作。
  • String 不可变,拼接多用 StringBuilder。
  • File 操作路径注意跨平台分隔符。
  • 枚举用于固定常量集合,功能强大。

这些类在日常开发中几乎天天使用,建议结合 JDK 源码加深理解。

csharp 复制代码
今天这篇文章就到这里了,大厦之成,非一木之材也;大海之阔,非一流之归也。感谢大家观看本文
相关推荐
weixin_523185321 小时前
Java基础知识总结(四):引用数据类型与参数传递机制
java·开发语言·python
宸津-代码粉碎机2 小时前
Spring AI企业级实战|从RAG优化到Agent多工具调度
java·大数据·人工智能·后端·python·spring
噢,我明白了2 小时前
QueryWrapper的使用
java
Chase_______2 小时前
【Java基础 | 15】集合框架(中):Set、HashSet、TreeSet 与哈希表
java·windows·散列表
摇滚侠2 小时前
Maven 入门+高深 微服务案例 122-125
java·微服务·maven
QuZero3 小时前
Guava Cache Deep Dive
java·后端·算法·guava
人道领域3 小时前
【LeetCode刷题日记】93.复原IP地址
java·开发语言·算法·leetcode
摇滚侠3 小时前
JavaWeb 全套教程 Listener 112-113
java·开发语言·servlet·tomcat·intellij-idea
曹牧3 小时前
Java:Deprecated 是
java·开发语言