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 {
@Override
public 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() {
@Override
public 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) {
// 简化写法:单条返回语句可省略 {} 和 return
ReturnNoParam 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)。
更多推荐
所有评论(0)