Java 进阶:IO 流与 Lambda 表达式深度解析
Java-day18
引入
Java 中的 IO 流是数据传输的核心机制,负责实现程序与文件、网络等设备的数据交互;而 Lambda 表达式则是 Java 8 引入的函数式编程特性,彻底简化了代码编写,尤其在多线程、集合操作等场景中大放异彩。本文将先深入解析 IO 流的分类与实战用法,再系统讲解 Lambda 表达式的思想、语法与练习,帮助读者掌握这两大实用技术。
一、IO 流:数据传输的“管道”
1.1 IO 流的分类与核心概念
IO 流是 Java 中用于**数据输入/输出**的核心机制,主要分为两类:
- **字符流**:处理文本数据(如 .java、.txt 文件),基于字符编码(如 UTF-8),核心类为 Reader 和 Writer;
- **字节流**:处理二进制数据(如图片、音频文件),基于字节(8 位)传输,核心类为 InputStream 和 OutputStream。
1.2 字符流实战:文本文件的读写
(1)字符输出流 Writer 及其实现类 FileWriter
Writer 是字符输出流的抽象基类,FileWriter 用于向文件写入字符数据。
``java
package com.qcby;import java.io.FileWriter;import java.io.IOException;import java.io.Writer;public class WriterExample {public static void main(String[] args) {// try-with-resources 自动关闭资源try (Writer writer = new FileWriter("output.txt")) {// 1. 写入单个字符writer.write('H');// 2. 写入字符数组char[] array = {'e', 'l', 'l', 'o'};writer.write(array);// 3. 写入字符数组的一部分writer.write(array, 1, 2); // 写入 "ll"// 4. 写入字符串writer.write(", World!");// 5. 写入字符串的一部分String str = "\nThis is Java IO.";writer.write(str, 0, 11); // 写入 "This is Java"System.out.println("数据已写入文件!");} catch (IOException e) {e.printStackTrace();}}}```
(2)字符输入流 Reader 及其实现类 FileReader
Reader 是字符输入流的抽象基类,FileReader 用于从文件读取字符数据。
```java
package com.qcby;import java.io.FileReader;import java.io.IOException;import java.io.Reader;public class ReaderExample {public static void main(String[] args) {try (Reader reader = new FileReader("output.txt")) {int data;while ((data = reader.read()) != -1) {System.out.print((char) data);}} catch (IOException e) {e.printStackTrace();}}}```
1.3 字节流实战:二进制文件的读写
(1)字节输入流 InputStream 及其实现类 FileInputStream
InputStream 是字节输入流的抽象基类,FileInputStream 用于从文件读取字节数据。
```java
package com.qcby;import java.io.FileInputStream;import java.io.IOException;public class FileInputStreamTest {public static void main(String[] args) {FileInputStream fis = null;try {fis = new FileInputStream("hello.txt");byte[] buffer = new byte[5];int len;while ((len = fis.read(buffer)) != -1) {System.out.print(new String(buffer, 0, len));}} catch (IOException e) {e.printStackTrace();} finally {if (fis != null) {try {fis.close();} catch (IOException e) {e.printStackTrace();}}}}}```
(2)字节输出流 OutputStream 及其实现类 FileOutputStream
OutputStream 是字节输出流的抽象基类,FileOutputStream 用于向文件写入字节数据。
```java
package com.qcby;import java.io.FileOutputStream;import java.io.IOException;public class FileOutputStreamTest {public static void main(String[] args) {FileOutputStream fos = null;try {fos = new FileOutputStream("hello.txt");fos.write(97); // 写入字符 'a'(ASCII 码 97)fos.write("中国人!\r\n".getBytes());fos.write("ABCDEFGH".getBytes(), 2, 4); // 写入 "CDEF"} catch (IOException e) {e.printStackTrace();} finally {if (fos != null) {try {fos.close();} catch (IOException e) {e.printStackTrace();}}}}}```
二、Lambda 表达式:函数式编程的简化艺术
2.1 函数式编程思想概述
- 数学中的函数:有输入量和输出量的计算方案,核心是 “对数据做操作”;
- 面向对象编程:强调 “通过对象做事”,必须依赖类和对象的语法结构;
- 函数式编程:忽略对象的复杂语法,强调 “做什么”,而非 “以什么形式做”,Lambda 表达式是其核心体现。
Lambda 表达式的核心价值:简化 “只有一个抽象方法的接口(函数式接口)” 的实现代码,消除冗余的匿名内部类。
2.2 体验 Lambda 表达式:多线程案例
需求:启动一个线程,在控制台输出 “多线程启动了”,对比三种实现方式。
(1)方案 1:传统实现 Runnable 接口
```java
运行
// 1. 定义实现类
class MyRunnable implements Runnable {@Overridepublic void run() {System.out.println("多线程启动了");}
}public class LambdaDemo {public static void main(String[] args) {// 2. 创建实现类对象MyRunnable myRunnable = new MyRunnable();// 3. 创建线程并启动new Thread(myRunnable).start();}
}
问题:代码冗余,仅为了实现一个简单的 run() 方法,需要定义完整的类。
(2)方案 2:匿名内部类改进
```java
运行
public class LambdaDemo {public static void main(String[] args) {// 匿名内部类:省略实现类定义new Thread(new Runnable() {@Overridepublic void run() {System.out.println("多线程启动了");}}).start();}
}
优化:减少了类定义,但仍保留了 new Runnable()、@Override 等冗余语法。
(3)方案 3:Lambda 表达式终极简化
java
运行
public class LambdaDemo {public static void main(String[] args) {// Lambda 表达式:仅保留核心逻辑new Thread(() -> {System.out.println("多线程启动了");}).start();}
}
核心:Runnable 是函数式接口(仅一个抽象方法 run()),Lambda 表达式直接替代其实现,只关注 “要做的事情”。
2.3 Lambda 表达式的标准格式
Lambda 表达式由三要素组成:形式参数、箭头、代码块,语法格式固定:
plaintext
(形式参数) -> { 代码块 }
- 形式参数:函数式接口中抽象方法的参数列表;无参数则留空
(),多个参数用逗号分隔; - ->:固定语法,读作 “箭头”,表示 “执行以下操作”;
- 代码块:抽象方法的实现逻辑,即要做的事情;若代码块只有一行,可省略
{}和;(return 也可省略)。
2.4 Lambda 表达式的使用前提
- 必须有一个函数式接口(接口中仅有一个抽象方法,可加
@FunctionalInterface注解校验); - 需通过该接口的引用接收 Lambda 表达式(或作为方法参数传递)。
2.5 Lambda 表达式实战练习
下面通过不同参数和返回值的函数式接口,练习 Lambda 表达式的用法。
(1)练习 1:无参无返回值
```java
运行
// 函数式接口(无参无返回)
@FunctionalInterface
interface NoReturnNoParam {void method();
}public class LambdaExercise {public static void main(String[] args) {// Lambda 实现NoReturnNoParam demo = () -> {System.out.println("无参无返回值的 Lambda 表达式");};demo.method(); // 调用方法}
}
(2)练习 2:单参数无返回值
java
运行
// 函数式接口(单参数无返回)
@FunctionalInterface
interface NoReturnOneParam {void method(int a);
}public class LambdaExercise {public static void main(String[] args) {// 简化写法:参数类型可省略NoReturnOneParam demo = (a) -> {System.out.println("单参数无返回值:" + a);};demo.method(6); // 输出:单参数无返回值:6}
}
(3)练习 3:多参数无返回值
```java
运行
// 函数式接口(多参数无返回)
@FunctionalInterface
interface NoReturnMultiParam {void method(int a, int b);
}public class LambdaExercise {public static void main(String[] args) {NoReturnMultiParam demo = (a, b) -> {System.out.println("多参数无返回值:a=" + a + ", b=" + b);};demo.method(3, 5); // 输出:多参数无返回值:a=3, b=5}
}
(4)练习 4:无参有返回值
```java
运行
// 函数式接口(无参有返回)
@FunctionalInterface
interface ReturnNoParam {int method();
}public class LambdaExercise {public static void main(String[] args) {// 简化写法:单条返回语句可省略 {} 和 returnReturnNoParam demo = () -> 100;int result = demo.method();System.out.println("无参有返回值:" + result); // 输出:100}
}
(5)练习 5:单参数有返回值
```java
运行
// 函数式接口(单参数有返回)
@FunctionalInterface
interface ReturnOneParam {int method(int a);
}public class LambdaExercise {public static void main(String[] args) {ReturnOneParam demo = (a) -> a * 2; // 简化写法int result = demo.method(6);System.out.println("单参数有返回值:" + result); // 输出:12}
}
(6)练习 6:多参数有返回值
```java
运行
// 函数式接口(多参数有返回)
@FunctionalInterface
interface ReturnMultiParam {int method(int a, int b);
}public class LambdaExercise {public static void main(String[] args) {ReturnMultiParam demo = (a, b) -> a + b; // 求和int result = demo.method(6, 8);System.out.println("多参数有返回值:" + result); // 输出:14}
}
三、总结:IO 流与 Lambda 表达式核心要点
1. IO 流核心
- 分类:字节流(
InputStream/OutputStream)处理所有文件,字符流(Reader/Writer)处理文本; - 实战:
FileInputStream/FileOutputStream用于字节读写,FileReader/FileWriter用于文本读写; - 关键:必须释放资源(推荐
try-with-resources),避免路径错误和编码乱码。
2. Lambda 表达式核心
- 思想:函数式编程,强调 “做什么” 而非 “形式”;
- 格式:
(参数) -> { 代码块 },可根据场景简化; - 前提:依赖函数式接口(仅一个抽象方法);
- 优势:简化匿名内部类代码,提高开发效率,尤其适用于多线程、集合排序等场景。
通过本文的学习,你已掌握 Java IO 流的实战用法和 Lambda 表达式的完整语法。IO 流是数据交互的基础,Lambda 是代码简化的利器,二者结合能让你的 Java 代码更高效、更简洁。后续可进一步学习 IO 流的高级用法(如缓冲流、转换流)和 Lambda 表达式在集合中的应用(如 stream API)。
