异常、实用类与I/O流进阶

1. 异常处理:不只是try-catch

异常体系

· Throwable → Error(系统内部错误,不可处理) & Exception
· Exception → RuntimeException(未检查异常) & 其他检查异常(如 IOException)

关键点:

· 检查异常必须throws或try-catch,未检查异常(如NullPointerException)不强制。
· finally总会执行,除非调用System.exit()。
· try-with-resources(Java 7+):自动关闭实现了AutoCloseable的资源。

```java
try (BufferedReader br = new BufferedReader(new FileReader("test.txt"))) {
    System.out.println(br.readLine());
} catch (IOException e) {
    e.printStackTrace();
} // 无需finally显式关闭br
```

自定义异常:继承Exception或RuntimeException,提供带message的构造方法。

---

2. 常用实用类(java.lang & java.util)

2.1 Objects 类(Java 7+)

· Objects.requireNonNull(T obj, String message):参数校验利器。
· Objects.equals(a, b):安全比较,允许null。

2.2 Optional 类(Java 8+)

解决null导致的空指针,鼓励函数式风格。

```java
Optional<String> opt = Optional.ofNullable(getString());
opt.ifPresent(s -> System.out.println("长度:" + s.length()));
String result = opt.orElse("默认值");
```

2.3 StringJoiner(Java 8+)

高效拼接带分隔符的字符串。

```java
StringJoiner sj = new StringJoiner(", ", "[", "]");
sj.add("A").add("B").add("C");
System.out.println(sj);  // [A, B, C]
```

2.4 正则匹配(Pattern & Matcher)

· Pattern:编译正则表达式(Pattern.compile("\\d+"))。
· Matcher:匹配、查找、替换。

```java
Matcher m = Pattern.compile("\\b\\w+\\b").matcher("Hello world!");
while (m.find()) {
    System.out.println(m.group());
}
```

---

3. I/O流进阶:字符流与缓冲流

3.1 字节流 vs 字符流

· 字节流(InputStream/OutputStream):处理二进制数据(图片、音频)。
· 字符流(Reader/Writer):处理文本,自动处理字符编码(UTF-8, GBK等)。
· 转换流:InputStreamReader / OutputStreamWriter 连接字节流与字符流。

```java
try (InputStreamReader isr = new InputStreamReader(new FileInputStream("data.txt"), StandardCharsets.UTF_8);
     BufferedReader br = new BufferedReader(isr)) {
    String line;
    while ((line = br.readLine()) != null) {
        System.out.println(line);
    }
}
```

3.2 缓冲流效率原理

· BufferedReader / BufferedWriter 内部维护char[]数组,减少底层系统调用。
· BufferedInputStream / BufferedOutputStream 类似,但处理字节。
· 注意:flush() 确保缓冲区数据写出。

3.3 标准输入输出重定向

· System.setIn(InputStream) / System.setOut(PrintStream) 可重定向标准输入输出。

---

4. 小型案例:单词统计工具

功能:从文本文件读取,统计每个单词出现次数,输出到另一个文件。
涉及:try-with-resources、BufferedReader、BufferedWriter、正则提取单词、Map<String, Integer>、StringJoiner。

```java
public class WordCounter {
    public static void main(String[] args) {
        Map<String, Integer> map = new HashMap<>();
        Pattern wordPattern = Pattern.compile("\\b\\w+\\b");
        try (BufferedReader br = new BufferedReader(new FileReader("input.txt"));
             BufferedWriter bw = new BufferedWriter(new FileWriter("output.txt"))) {
            String line;
            while ((line = br.readLine()) != null) {
                Matcher m = wordPattern.matcher(line.toLowerCase());
                while (m.find()) {
                    String w = m.group();
                    map.put(w, map.getOrDefault(w, 0) + 1);
                }
            }
            // 写入结果
            for (var entry : map.entrySet()) {
                bw.write(entry.getKey() + " : " + entry.getValue());
                bw.newLine();
            }
        } catch (IOException e) {
            System.err.println("文件处理出错:" + e.getMessage());
        }
    }
}
```

---

5. 常见易错点(面试/考试高频)

· catch 顺序:子类异常在前,父类在后(否则编译错误)。
· return 与 finally:如果finally中有return,会覆盖try中的return。
· Scanner 与 BufferedReader 选择:
  · Scanner:方便解析类型(nextInt()等),但内部用正则,稍慢。
  · BufferedReader + split():更轻量高效,适合逐行处理。
· 字符编码问题:不指定编码时使用系统默认编码,易导致跨平台乱码,应显式指定StandardCharsets.UTF_8。

Logo

CANN开发者社区旨在汇聚广大开发者,围绕CANN架构重构、算子开发、部署应用优化等核心方向,展开深度交流与思想碰撞,携手共同促进CANN开放生态突破!

更多推荐