🚀 第二阶段:Java进阶技能③Java新特性
💡 学习目标:掌握Java 8+的现代特性,包括Lambda表达式、Stream API、新日期时间API和模块化系统,提升编程效率和代码质量
🔗 Lambda表达式与函数式编程
🎯 Lambda表达式概述
🌟 Lambda表达式:Java 8引入的函数式编程特性,允许将函数作为参数传递,简化代码编写
✨ Lambda表达式的核心优势
| 优势 | 说明 | 示例 |
|---|---|---|
| 📝 简化代码 | 减少样板代码 | (x, y) -> x + y 替代匿名内部类 |
| 🚀 提高可读性 | 代码更加简洁明了 | 函数式风格更直观 |
| 🔧 支持函数式编程 | 函数作为一等公民 | 高阶函数、函数组合 |
| ⚡ 性能优化 | 编译器优化 | 避免创建多余的匿名类 |
🏗️ Lambda表达式语法
📋 基本语法格式
// 完整格式
(参数列表) -> {
// 方法体
return 结果;
}
// 简化格式(单表达式)
(参数列表) -> 表达式
// 单参数可省略括号
参数 -> 表达式
// 无参数
() -> 表达式
💻 Lambda表达式实战
🎯 基础Lambda示例
🎯 示例1:Lambda表达式基础用法
import java.util.*;
import java.util.function.*;
public class LambdaBasicsDemo {
public static void main(String[] args) {
System.out.println("=== Lambda表达式基础演示 ===");
// 1. 替代匿名内部类
System.out.println("\n1. 线程创建对比:");
// 传统方式
Thread oldThread = new Thread(new Runnable() {
@Override
public void run() {
System.out.println("传统方式创建线程");
}
});
// Lambda方式
Thread newThread = new Thread(() -> {
System.out.println("Lambda方式创建线程");
});
oldThread.start();
newThread.start();
// 2. 集合操作
System.out.println("\n2. 集合排序对比:");
List<String> names = Arrays.asList("张三", "李四", "王五", "赵六");
// 传统方式排序
List<String> traditionalSort = new ArrayList<>(names);
Collections.sort(traditionalSort, new Comparator<String>() {
@Override
public int compare(String s1, String s2) {
return s1.length() - s2.length();
}
});
System.out.println("传统排序结果: " + traditionalSort);
// Lambda方式排序
List<String> lambdaSort = new ArrayList<>(names);
lambdaSort.sort((s1, s2) -> s1.length() - s2.length());
System.out.println("Lambda排序结果: " + lambdaSort);
// 3. 函数式接口使用
System.out.println("\n3. 函数式接口演示:");
// Predicate - 判断条件
Predicate<String> isLongName = name -> name.length() > 2;
System.out.println("张三 是长名字吗? " + isLongName.test("张三"));
System.out.println("张三丰 是长名字吗? " + isLongName.test("张三丰"));
// Function - 转换函数
Function<String, Integer> getLength = String::length;
System.out.println("'Hello World' 的长度: " + getLength.apply("Hello World"));
// Consumer - 消费者
Consumer<String> printer = System.out::println;
names.forEach(printer);
// Supplier - 供应者
Supplier<String> randomName = () -> {
String[] namePool = {"小明", "小红", "小刚", "小丽"};
return namePool[new Random().nextInt(namePool.length)];
};
System.out.println("随机名字: " + randomName.get());
}
}
🔧 高级Lambda应用
🎯 示例2:高级Lambda特性
import java.util.*;
import java.util.function.*;
public class AdvancedLambdaDemo {
// 自定义函数式接口
@FunctionalInterface
interface Calculator {
double calculate(double a, double b);
// 默认方法
default String getDescription() {
return "数学计算器";
}
}
// 高阶函数示例
public static Function<Integer, Integer> createMultiplier(int factor) {
return x -> x * factor;
}
// 函数组合示例
public static void demonstrateFunctionComposition() {
System.out.println("=== 函数组合演示 ===");
Function<String, String> addPrefix = s -> "前缀-" + s;
Function<String, String> addSuffix = s -> s + "-后缀";
Function<String, String> toUpper = String::toUpperCase;
// 函数组合
Function<String, String> combined = addPrefix
.andThen(addSuffix)
.andThen(toUpper);
String result = combined.apply("测试");
System.out.println("组合函数结果: " + result);
}
public static void main(String[] args) {
System.out.println("=== 高级Lambda特性演示 ===");
// 1. 自定义函数式接口
System.out.println("\n1. 自定义函数式接口:");
Calculator add = (a, b) -> a + b;
Calculator multiply = (a, b) -> a * b;
Calculator power = Math::pow;
System.out.println("5 + 3 = " + add.calculate(5, 3));
System.out.println("5 * 3 = " + multiply.calculate(5, 3));
System.out.println("5 ^ 3 = " + power.calculate(5, 3));
System.out.println("描述: " + add.getDescription());
// 2. 高阶函数
System.out.println("\n2. 高阶函数:");
Function<Integer, Integer> doubler = createMultiplier(2);
Function<Integer, Integer> tripler = createMultiplier(3);
System.out.println("10 * 2 = " + doubler.apply(10));
System.out.println("10 * 3 = " + tripler.apply(10));
// 3. 函数组合
demonstrateFunctionComposition();
// 4. 闭包示例
System.out.println("\n4. 闭包示例:");
int baseValue = 100;
Function<Integer, Integer> addBase = x -> x + baseValue; // 捕获外部变量
System.out.println("50 + 100 = " + addBase.apply(50));
// 5. 方法引用
System.out.println("\n5. 方法引用:");
List<String> words = Arrays.asList("apple", "banana", "cherry", "date");
// 静态方法引用
words.sort(String::compareToIgnoreCase);
System.out.println("排序后: " + words);
// 实例方法引用
words.forEach(System.out::println);
// 构造器引用
Supplier<List<String>> listSupplier = ArrayList::new;
List<String> newList = listSupplier.get();
System.out.println("新列表: " + newList);
}
}
🌊 Stream API详解
🎯 Stream API概述
🌟 Stream API:Java 8引入的数据处理API,提供声明式的数据操作方式,支持函数式编程风格
✨ Stream API核心特性
🌊 Stream API特性
│
├── 🔄 声明式编程
│ ├── 描述"做什么"而非"怎么做"
│ └── 代码更简洁易读
│
├── 🔗 链式操作
│ ├── 中间操作(Intermediate)
│ └── 终端操作(Terminal)
│
├── ⚡ 延迟执行
│ ├── 中间操作不立即执行
│ └── 终端操作触发计算
│
└── 🚀 并行处理
├── 自动并行化
└── 充分利用多核CPU
💻 Stream基础操作
🎯 创建Stream和基本操作
🎯 示例3:Stream基础操作
import java.util.*;
import java.util.stream.*;
public class StreamBasicsDemo {
public static void main(String[] args) {
System.out.println("=== Stream基础操作演示 ===");
// 1. 创建Stream的多种方式
System.out.println("\n1. 创建Stream:");
// 从集合创建
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
Stream<Integer> fromList = numbers.stream();
// 从数组创建
String[] words = {"apple", "banana", "cherry"};
Stream<String> fromArray = Arrays.stream(words);
// 使用Stream.of()
Stream<String> fromValues = Stream.of("Java", "Python", "JavaScript");
// 无限流
Stream<Integer> infiniteStream = Stream.iterate(0, n -> n + 2);
Stream<Double> randomStream = Stream.generate(Math::random);
// 2. 过滤操作(filter)
System.out.println("\n2. 过滤操作:");
List<Integer> evenNumbers = numbers.stream()
.filter(n -> n % 2 == 0)
.collect(Collectors.toList());
System.out.println("偶数: " + evenNumbers);
// 3. 映射操作(map)
System.out.println("\n3. 映射操作:");
List<Integer> squares = numbers.stream()
.map(n -> n * n)
.collect(Collectors.toList());
System.out.println("平方数: " + squares);
// 4. 排序操作(sorted)
System.out.println("\n4. 排序操作:");
List<String> sortedWords = Arrays.stream(words)
.sorted()
.collect(Collectors.toList());
System.out.println("排序后: " + sortedWords);
// 5. 去重操作(distinct)
System.out.println("\n5. 去重操作:");
List<Integer> duplicates = Arrays.asList(1, 2, 2, 3, 3, 3, 4, 4, 5);
List<Integer> unique = duplicates.stream()
.distinct()
.collect(Collectors.toList());
System.out.println("去重后: " + unique);
// 6. 限制操作(limit/skip)
System.out.println("\n6. 限制操作:");
List<Integer> first5 = numbers.stream()
.limit(5)
.collect(Collectors.toList());
System.out.println("前5个: " + first5);
List<Integer> skip5 = numbers.stream()
.skip(5)
.collect(Collectors.toList());
System.out.println("跳过前5个: " + skip5);
}
}
🔧 Stream高级操作
🎯 示例4:Stream高级特性
import java.util.*;
import java.util.stream.*;
public class AdvancedStreamDemo {
// 学生类
static class Student {
private String name;
private int age;
private String major;
private double score;
public Student(String name, int age, String major, double score) {
this.name = name;
this.age = age;
this.major = major;
this.score = score;
}
// getter方法
public String getName() { return name; }
public int getAge() { return age; }
public String getMajor() { return major; }
public double getScore() { return score; }
@Override
public String toString() {
return String.format("Student{name='%s', age=%d, major='%s', score=%.1f}",
name, age, major, score);
}
}
public static void main(String[] args) {
System.out.println("=== Stream高级操作演示 ===");
// 创建学生数据
List<Student> students = Arrays.asList(
new Student("张三", 20, "计算机", 85.5),
new Student("李四", 21, "数学", 92.0),
new Student("王五", 19, "计算机", 78.5),
new Student("赵六", 22, "物理", 88.0),
new Student("钱七", 20, "数学", 95.5),
new Student("孙八", 21, "计算机", 82.0)
);
// 1. 分组操作(groupingBy)
System.out.println("\n1. 按专业分组:");
Map<String, List<Student>> byMajor = students.stream()
.collect(Collectors.groupingBy(Student::getMajor));
byMajor.forEach((major, studentList) -> {
System.out.println(major + ": " + studentList.size() + "人");
});
// 2. 分区操作(partitioningBy)
System.out.println("\n2. 按成绩分区(>=90分):");
Map<Boolean, List<Student>> byScore = students.stream()
.collect(Collectors.partitioningBy(s -> s.getScore() >= 90));
System.out.println("优秀学生: " + byScore.get(true).size() + "人");
System.out.println("普通学生: " + byScore.get(false).size() + "人");
// 3. 统计操作
System.out.println("\n3. 成绩统计:");
DoubleSummaryStatistics scoreStats = students.stream()
.mapToDouble(Student::getScore)
.summaryStatistics();
System.out.println("平均分: " + scoreStats.getAverage());
System.out.println("最高分: " + scoreStats.getMax());
System.out.println("最低分: " + scoreStats.getMin());
System.out.println("总人数: " + scoreStats.getCount());
// 4. 查找操作
System.out.println("\n4. 查找操作:");
Optional<Student> topStudent = students.stream()
.max(Comparator.comparing(Student::getScore));
topStudent.ifPresent(s -> System.out.println("最高分学生: " + s));
boolean hasExcellent = students.stream()
.anyMatch(s -> s.getScore() >= 95);
System.out.println("是否有95分以上学生: " + hasExcellent);
// 5. 归约操作(reduce)
System.out.println("\n5. 归约操作:");
double totalScore = students.stream()
.mapToDouble(Student::getScore)
.reduce(0.0, Double::sum);
System.out.println("总分: " + totalScore);
Optional<Student> oldestStudent = students.stream()
.reduce((s1, s2) -> s1.getAge() > s2.getAge() ? s1 : s2);
oldestStudent.ifPresent(s -> System.out.println("年龄最大学生: " + s));
// 6. 并行流
System.out.println("\n6. 并行流性能对比:");
List<Integer> largeList = IntStream.rangeClosed(1, 1000000)
.boxed()
.collect(Collectors.toList());
long startTime = System.currentTimeMillis();
long sequentialSum = largeList.stream()
.mapToLong(Integer::longValue)
.sum();
long sequentialTime = System.currentTimeMillis() - startTime;
startTime = System.currentTimeMillis();
long parallelSum = largeList.parallelStream()
.mapToLong(Integer::longValue)
.sum();
long parallelTime = System.currentTimeMillis() - startTime;
System.out.println("顺序流耗时: " + sequentialTime + "ms, 结果: " + sequentialSum);
System.out.println("并行流耗时: " + parallelTime + "ms, 结果: " + parallelSum);
}
}
⏰ 新日期时间API
🎯 新日期时间API概述
🌟 新日期时间API:Java 8引入的java.time包,解决了传统Date和Calendar类的诸多问题
✨ 新API的核心优势
| 特性 | 传统API问题 | 新API解决方案 |
|---|---|---|
| 🔒 不可变性 | Date类可变,线程不安全 | 所有类都是不可变的 |
| 🎯 类型安全 | 月份从0开始,容易出错 | 月份从1开始,更直观 |
| 📅 功能完整 | 功能分散在多个类中 | 职责明确,功能集中 |
| 🌍 时区支持 | 时区处理复杂 | 内置完善的时区支持 |
| 📖 可读性 | API设计不够直观 | 链式调用,语义清晰 |
💻 核心日期时间类
🎯 基础日期时间操作
🎯 示例5:新日期时间API基础
import java.time.*;
import java.time.format.DateTimeFormatter;
import java.time.temporal.ChronoUnit;
public class DateTimeBasicsDemo {
public static void main(String[] args) {
System.out.println("=== 新日期时间API演示 ===");
// 1. 基本日期时间类
System.out.println("\n1. 基本日期时间类:");
// LocalDate - 日期
LocalDate today = LocalDate.now();
LocalDate birthday = LocalDate.of(1990, 5, 15);
System.out.println("今天: " + today);
System.out.println("生日: " + birthday);
// LocalTime - 时间
LocalTime now = LocalTime.now();
LocalTime meetingTime = LocalTime.of(14, 30, 0);
System.out.println("现在时间: " + now);
System.out.println("会议时间: " + meetingTime);
// LocalDateTime - 日期时间
LocalDateTime currentDateTime = LocalDateTime.now();
LocalDateTime appointmentTime = LocalDateTime.of(2024, 12, 25, 10, 30);
System.out.println("当前日期时间: " + currentDateTime);
System.out.println("预约时间: " + appointmentTime);
// 2. 日期计算
System.out.println("\n2. 日期计算:");
LocalDate nextWeek = today.plusWeeks(1);
LocalDate lastMonth = today.minusMonths(1);
LocalDate nextYear = today.plusYears(1);
System.out.println("下周: " + nextWeek);
System.out.println("上个月: " + lastMonth);
System.out.println("明年: " + nextYear);
// 3. 时间间隔计算
System.out.println("\n3. 时间间隔:");
long daysBetween = ChronoUnit.DAYS.between(birthday, today);
long yearsBetween = ChronoUnit.YEARS.between(birthday, today);
System.out.println("距离生日已过: " + daysBetween + " 天");
System.out.println("年龄: " + yearsBetween + " 岁");
// 4. 日期比较
System.out.println("\n4. 日期比较:");
LocalDate date1 = LocalDate.of(2024, 1, 1);
LocalDate date2 = LocalDate.of(2024, 12, 31);
System.out.println("date1 在 date2 之前: " + date1.isBefore(date2));
System.out.println("date1 在 date2 之后: " + date1.isAfter(date2));
System.out.println("date1 等于 today: " + date1.isEqual(today));
// 5. 获取日期信息
System.out.println("\n5. 日期信息:");
System.out.println("年份: " + today.getYear());
System.out.println("月份: " + today.getMonth() + " (" + today.getMonthValue() + ")");
System.out.println("日期: " + today.getDayOfMonth());
System.out.println("星期: " + today.getDayOfWeek());
System.out.println("一年中的第几天: " + today.getDayOfYear());
}
}
🌍 时区和格式化
🎯 示例6:时区处理和格式化
import java.time.*;
import java.time.format.DateTimeFormatter;
import java.time.format.FormatStyle;
import java.util.Locale;
public class DateTimeAdvancedDemo {
public static void main(String[] args) {
System.out.println("=== 高级日期时间操作演示 ===");
// 1. 时区处理
System.out.println("\n1. 时区处理:");
// 带时区的日期时间
ZonedDateTime beijingTime = ZonedDateTime.now(ZoneId.of("Asia/Shanghai"));
ZonedDateTime newYorkTime = ZonedDateTime.now(ZoneId.of("America/New_York"));
ZonedDateTime londonTime = ZonedDateTime.now(ZoneId.of("Europe/London"));
System.out.println("北京时间: " + beijingTime);
System.out.println("纽约时间: " + newYorkTime);
System.out.println("伦敦时间: " + londonTime);
// 时区转换
ZonedDateTime beijingToNewYork = beijingTime.withZoneSameInstant(ZoneId.of("America/New_York"));
System.out.println("北京时间转纽约时间: " + beijingToNewYork);
// 2. 日期格式化
System.out.println("\n2. 日期格式化:");
LocalDateTime now = LocalDateTime.now();
// 预定义格式
System.out.println("ISO格式: " + now.format(DateTimeFormatter.ISO_LOCAL_DATE_TIME));
System.out.println("基本ISO格式: " + now.format(DateTimeFormatter.BASIC_ISO_DATE));
// 本地化格式
System.out.println("中文长格式: " + now.format(DateTimeFormatter.ofLocalizedDateTime(FormatStyle.FULL).withLocale(Locale.CHINA)));
System.out.println("中文短格式: " + now.format(DateTimeFormatter.ofLocalizedDateTime(FormatStyle.SHORT).withLocale(Locale.CHINA)));
// 自定义格式
DateTimeFormatter customFormatter = DateTimeFormatter.ofPattern("yyyy年MM月dd日 HH:mm:ss");
System.out.println("自定义格式: " + now.format(customFormatter));
DateTimeFormatter englishFormatter = DateTimeFormatter.ofPattern("EEEE, MMMM dd, yyyy 'at' HH:mm", Locale.ENGLISH);
System.out.println("英文格式: " + now.format(englishFormatter));
// 3. 字符串解析
System.out.println("\n3. 字符串解析:");
String dateString = "2024-12-25 15:30:45";
LocalDateTime parsed = LocalDateTime.parse(dateString, DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
System.out.println("解析结果: " + parsed);
// 4. Period和Duration
System.out.println("\n4. 时间段计算:");
// Period - 日期间隔
LocalDate startDate = LocalDate.of(2020, 1, 1);
LocalDate endDate = LocalDate.of(2024, 12, 31);
Period period = Period.between(startDate, endDate);
System.out.println("时间间隔: " + period.getYears() + "年" + period.getMonths() + "月" + period.getDays() + "天");
// Duration - 时间间隔
LocalTime startTime = LocalTime.of(9, 0);
LocalTime endTime = LocalTime.of(17, 30);
Duration duration = Duration.between(startTime, endTime);
System.out.println("工作时长: " + duration.toHours() + "小时" + (duration.toMinutes() % 60) + "分钟");
// 5. 实用工具方法
System.out.println("\n5. 实用工具:");
// 判断闰年
System.out.println("2024年是闰年: " + Year.of(2024).isLeap());
System.out.println("2023年是闰年: " + Year.of(2023).isLeap());
// 月份天数
YearMonth yearMonth = YearMonth.of(2024, 2);
System.out.println("2024年2月有 " + yearMonth.lengthOfMonth() + " 天");
// 一年的天数
Year year2024 = Year.of(2024);
System.out.println("2024年有 " + year2024.length() + " 天");
}
}
🔧 Optional类详解
🎯 Optional概述
🌟 Optional:Java 8引入的容器类,用于优雅地处理可能为null的值,避免NullPointerException
✨ Optional的核心优势
| 优势 | 传统方式问题 | Optional解决方案 |
|---|---|---|
| 🛡️ 空值安全 | 容易出现NPE | 强制处理空值情况 |
| 📖 代码可读性 | 大量null检查 | 链式调用更清晰 |
| 🎯 意图明确 | 不知道是否可能为null | 明确表示可能为空 |
| 🔧 函数式风格 | 命令式编程 | 支持函数式操作 |
💻 Optional实战应用
🎯 Optional基础操作
🎯 示例7:Optional基础用法
import java.util.*;
import java.util.function.Predicate;
public class OptionalBasicsDemo {
// 用户类
static class User {
private String name;
private String email;
private Integer age;
public User(String name, String email, Integer age) {
this.name = name;
this.email = email;
this.age = age;
}
public String getName() { return name; }
public String getEmail() { return email; }
public Integer getAge() { return age; }
@Override
public String toString() {
return String.format("User{name='%s', email='%s', age=%d}", name, email, age);
}
}
// 模拟数据库查询
public static Optional<User> findUserById(int id) {
Map<Integer, User> users = Map.of(
1, new User("张三", "zhangsan@example.com", 25),
2, new User("李四", "lisi@example.com", 30),
3, new User("王五", null, 28) // 邮箱为空
);
return Optional.ofNullable(users.get(id));
}
public static void main(String[] args) {
System.out.println("=== Optional基础操作演示 ===");
// 1. 创建Optional
System.out.println("\n1. 创建Optional:");
// 创建空Optional
Optional<String> empty = Optional.empty();
System.out.println("空Optional: " + empty);
// 创建非空Optional
Optional<String> nonEmpty = Optional.of("Hello");
System.out.println("非空Optional: " + nonEmpty);
// 创建可能为空的Optional
Optional<String> nullable = Optional.ofNullable(null);
System.out.println("可能为空的Optional: " + nullable);
// 2. 检查值是否存在
System.out.println("\n2. 检查值:");
System.out.println("empty.isPresent(): " + empty.isPresent());
System.out.println("nonEmpty.isPresent(): " + nonEmpty.isPresent());
System.out.println("empty.isEmpty(): " + empty.isEmpty()); // Java 11+
// 3. 获取值
System.out.println("\n3. 获取值:");
// 安全获取值
if (nonEmpty.isPresent()) {
System.out.println("值: " + nonEmpty.get());
}
// 提供默认值
String value1 = empty.orElse("默认值");
String value2 = nonEmpty.orElse("默认值");
System.out.println("empty.orElse(): " + value1);
System.out.println("nonEmpty.orElse(): " + value2);
// 延迟计算默认值
String value3 = empty.orElseGet(() -> "计算得到的默认值");
System.out.println("empty.orElseGet(): " + value3);
// 4. 条件执行
System.out.println("\n4. 条件执行:");
nonEmpty.ifPresent(s -> System.out.println("值存在: " + s));
empty.ifPresent(s -> System.out.println("这不会执行"));
// Java 9+ ifPresentOrElse
nonEmpty.ifPresentOrElse(
s -> System.out.println("存在值: " + s),
() -> System.out.println("值不存在")
);
// 5. 实际应用示例
System.out.println("\n5. 实际应用:");
// 查找用户
Optional<User> user1 = findUserById(1);
Optional<User> user999 = findUserById(999);
// 传统方式处理
System.out.println("传统方式:");
User u1 = user1.orElse(null);
if (u1 != null) {
System.out.println("找到用户: " + u1.getName());
} else {
System.out.println("用户不存在");
}
// Optional方式处理
System.out.println("Optional方式:");
user1.ifPresentOrElse(
user -> System.out.println("找到用户: " + user.getName()),
() -> System.out.println("用户不存在")
);
user999.ifPresentOrElse(
user -> System.out.println("找到用户: " + user.getName()),
() -> System.out.println("用户不存在")
);
}
}
🔧 Optional高级操作
🎯 示例8:Optional高级特性
import java.util.*;
import java.util.stream.Stream;
public class OptionalAdvancedDemo {
static class Address {
private String street;
private String city;
private String country;
public Address(String street, String city, String country) {
this.street = street;
this.city = city;
this.country = country;
}
public String getStreet() { return street; }
public String getCity() { return city; }
public String getCountry() { return country; }
@Override
public String toString() {
return String.format("%s, %s, %s", street, city, country);
}
}
static class Person {
private String name;
private Optional<Address> address;
private Optional<String> phone;
public Person(String name, Address address, String phone) {
this.name = name;
this.address = Optional.ofNullable(address);
this.phone = Optional.ofNullable(phone);
}
public String getName() { return name; }
public Optional<Address> getAddress() { return address; }
public Optional<String> getPhone() { return phone; }
}
public static void main(String[] args) {
System.out.println("=== Optional高级操作演示 ===");
// 创建测试数据
Person person1 = new Person("张三",
new Address("中关村大街1号", "北京", "中国"),
"13800138000");
Person person2 = new Person("李四", null, null);
// 1. map操作 - 转换值
System.out.println("\n1. map操作:");
Optional<String> city1 = Optional.of(person1)
.map(Person::getAddress)
.flatMap(addr -> addr)
.map(Address::getCity);
System.out.println("张三的城市: " + city1.orElse("未知"));
Optional<String> city2 = Optional.of(person2)
.map(Person::getAddress)
.flatMap(addr -> addr)
.map(Address::getCity);
System.out.println("李四的城市: " + city2.orElse("未知"));
// 2. flatMap操作 - 扁平化嵌套Optional
System.out.println("\n2. flatMap操作:");
Optional<String> phone1 = Optional.of(person1)
.flatMap(Person::getPhone);
Optional<String> phone2 = Optional.of(person2)
.flatMap(Person::getPhone);
System.out.println("张三的电话: " + phone1.orElse("无电话"));
System.out.println("李四的电话: " + phone2.orElse("无电话"));
// 3. filter操作 - 条件过滤
System.out.println("\n3. filter操作:");
Optional<Person> beijingPerson = Optional.of(person1)
.filter(p -> p.getAddress()
.map(Address::getCity)
.orElse("")
.equals("北京"));
beijingPerson.ifPresentOrElse(
p -> System.out.println(p.getName() + " 住在北京"),
() -> System.out.println("不住在北京")
);
// 4. 链式操作组合
System.out.println("\n4. 链式操作:");
String result = Optional.of(person1)
.flatMap(Person::getAddress)
.map(Address::getCountry)
.filter(country -> country.equals("中国"))
.map(country -> "国内用户")
.orElse("国外用户");
System.out.println("用户类型: " + result);
// 5. Optional与Stream结合
System.out.println("\n5. Optional与Stream:");
List<Person> people = Arrays.asList(person1, person2);
// 获取所有有效的城市
List<String> cities = people.stream()
.map(Person::getAddress)
.filter(Optional::isPresent)
.map(Optional::get)
.map(Address::getCity)
.distinct()
.collect(ArrayList::new, ArrayList::add, ArrayList::addAll);
System.out.println("所有城市: " + cities);
// Java 9+ Optional.stream()
List<String> phones = people.stream()
.map(Person::getPhone)
.flatMap(Optional::stream)
.collect(ArrayList::new, ArrayList::add, ArrayList::addAll);
System.out.println("所有电话: " + phones);
// 6. 异常处理
System.out.println("\n6. 异常处理:");
Optional<Integer> number = parseInteger("123");
Optional<Integer> invalid = parseInteger("abc");
System.out.println("解析 '123': " + number.orElse(-1));
System.out.println("解析 'abc': " + invalid.orElse(-1));
// 7. Optional最佳实践
System.out.println("\n7. 最佳实践示例:");
demonstrateBestPractices();
}
// 安全的字符串转整数
public static Optional<Integer> parseInteger(String str) {
try {
return Optional.of(Integer.parseInt(str));
} catch (NumberFormatException e) {
return Optional.empty();
}
}
// Optional最佳实践
public static void demonstrateBestPractices() {
// ✅ 好的做法
Optional<String> goodExample = Optional.ofNullable(getValue())
.filter(s -> !s.isEmpty())
.map(String::toUpperCase);
goodExample.ifPresentOrElse(
value -> System.out.println("处理值: " + value),
() -> System.out.println("值为空或无效")
);
// ❌ 避免的做法
// 不要这样做:
// if (optional.isPresent()) {
// return optional.get();
// } else {
// return defaultValue;
// }
// 应该这样做:
String result = goodExample.orElse("默认值");
System.out.println("最终结果: " + result);
}
private static String getValue() {
return Math.random() > 0.5 ? "hello" : null;
}
}
📦 模块化系统(Java 9+)
🎯 模块化系统概述
🌟 模块化系统(JPMS):Java 9引入的模块化系统,提供更好的封装性、可靠性和可维护性
✨ 模块化的核心优势
📦 模块化系统特性
│
├── 🔒 强封装
│ ├── 明确的API边界
│ └── 隐藏内部实现
│
├── 🎯 可靠配置
│ ├── 编译时依赖检查
│ └── 避免运行时错误
│
├── 🚀 性能优化
│ ├── 更小的运行时镜像
│ └── 启动时间优化
│
└── 🛠️ 工具支持
├── jlink创建自定义运行时
└── 更好的IDE支持
💻 模块化实战
🎯 基础模块定义
🎯 示例9:模块化项目结构
// 项目结构示例
/*
my-modular-app/
├── src/
│ ├── com.example.utils/
│ │ ├── module-info.java
│ │ └── com/example/utils/
│ │ ├── StringUtils.java
│ │ └── MathUtils.java
│ ├── com.example.service/
│ │ ├── module-info.java
│ │ └── com/example/service/
│ │ ├── UserService.java
│ │ └── impl/
│ │ └── UserServiceImpl.java
│ └── com.example.app/
│ ├── module-info.java
│ └── com/example/app/
│ └── Application.java
*/
// 1. 工具模块 (com.example.utils)
// module-info.java
module com.example.utils {
// 导出包,使其他模块可以访问
exports com.example.utils;
}
// StringUtils.java
package com.example.utils;
public class StringUtils {
public static boolean isEmpty(String str) {
return str == null || str.trim().isEmpty();
}
public static String capitalize(String str) {
if (isEmpty(str)) {
return str;
}
return str.substring(0, 1).toUpperCase() + str.substring(1).toLowerCase();
}
public static String reverse(String str) {
if (isEmpty(str)) {
return str;
}
return new StringBuilder(str).reverse().toString();
}
}
// MathUtils.java
package com.example.utils;
public class MathUtils {
public static boolean isPrime(int number) {
if (number < 2) return false;
for (int i = 2; i <= Math.sqrt(number); i++) {
if (number % i == 0) return false;
}
return true;
}
public static int gcd(int a, int b) {
while (b != 0) {
int temp = b;
b = a % b;
a = temp;
}
return a;
}
}
// 2. 服务模块 (com.example.service)
// module-info.java
module com.example.service {
// 依赖工具模块
requires com.example.utils;
// 导出服务接口
exports com.example.service;
// 不导出实现包,保持封装性
// com.example.service.impl 包对外不可见
}
// UserService.java
package com.example.service;
import java.util.List;
import java.util.Optional;
public interface UserService {
Optional<User> findById(Long id);
List<User> findAll();
User save(User user);
void deleteById(Long id);
}
// User.java
package com.example.service;
public class User {
private Long id;
private String name;
private String email;
public User(Long id, String name, String email) {
this.id = id;
this.name = name;
this.email = email;
}
// getter和setter方法
public Long getId() { return id; }
public void setId(Long id) { this.id = id; }
public String getName() { return name; }
public void setName(String name) { this.name = name; }
public String getEmail() { return email; }
public void setEmail(String email) { this.email = email; }
@Override
public String toString() {
return String.format("User{id=%d, name='%s', email='%s'}", id, name, email);
}
}
// UserServiceImpl.java (内部实现,不对外暴露)
package com.example.service.impl;
import com.example.service.User;
import com.example.service.UserService;
import com.example.utils.StringUtils;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicLong;
public class UserServiceImpl implements UserService {
private final Map<Long, User> users = new ConcurrentHashMap<>();
private final AtomicLong idGenerator = new AtomicLong(1);
public UserServiceImpl() {
// 初始化一些测试数据
save(new User(null, "张三", "zhangsan@example.com"));
save(new User(null, "李四", "lisi@example.com"));
}
@Override
public Optional<User> findById(Long id) {
return Optional.ofNullable(users.get(id));
}
@Override
public List<User> findAll() {
return new ArrayList<>(users.values());
}
@Override
public User save(User user) {
if (user.getId() == null) {
user.setId(idGenerator.getAndIncrement());
}
// 使用工具模块的方法
if (!StringUtils.isEmpty(user.getName())) {
user.setName(StringUtils.capitalize(user.getName()));
}
users.put(user.getId(), user);
return user;
}
@Override
public void deleteById(Long id) {
users.remove(id);
}
}
// 3. 应用模块 (com.example.app)
// module-info.java
module com.example.app {
// 依赖服务模块
requires com.example.service;
requires com.example.utils;
// 如果需要使用反射访问,需要opens声明
// opens com.example.app to some.framework;
}
// Application.java
package com.example.app;
import com.example.service.User;
import com.example.service.UserService;
import com.example.service.impl.UserServiceImpl;
import com.example.utils.StringUtils;
public class Application {
public static void main(String[] args) {
System.out.println("=== 模块化应用演示 ===");
// 创建服务实例
UserService userService = new UserServiceImpl();
// 1. 查询所有用户
System.out.println("\n1. 所有用户:");
userService.findAll().forEach(System.out::println);
// 2. 添加新用户
System.out.println("\n2. 添加新用户:");
User newUser = new User(null, "王五", "wangwu@example.com");
User savedUser = userService.save(newUser);
System.out.println("保存的用户: " + savedUser);
// 3. 查询特定用户
System.out.println("\n3. 查询用户:");
userService.findById(1L).ifPresentOrElse(
user -> System.out.println("找到用户: " + user),
() -> System.out.println("用户不存在")
);
// 4. 使用工具类
System.out.println("\n4. 字符串工具演示:");
String text = "hello world";
System.out.println("原文: " + text);
System.out.println("首字母大写: " + StringUtils.capitalize(text));
System.out.println("反转: " + StringUtils.reverse(text));
// 5. 删除用户
System.out.println("\n5. 删除用户:");
userService.deleteById(2L);
System.out.println("删除后的用户列表:");
userService.findAll().forEach(System.out::println);
}
}
🆕 其他重要新特性
🎯 接口默认方法和静态方法
💻 接口增强特性
🎯 示例10:接口新特性
import java.util.*;
import java.util.function.Predicate;
// 增强的接口定义
public interface EnhancedCollection<T> {
// 抽象方法
List<T> getItems();
// 默认方法 - 提供默认实现
default int size() {
return getItems().size();
}
default boolean isEmpty() {
return getItems().isEmpty();
}
default void forEach(java.util.function.Consumer<? super T> action) {
getItems().forEach(action);
}
default List<T> filter(Predicate<T> predicate) {
return getItems().stream()
.filter(predicate)
.collect(ArrayList::new, ArrayList::add, ArrayList::addAll);
}
// 静态方法 - 工具方法
static <T> EnhancedCollection<T> of(T... items) {
return new SimpleEnhancedCollection<>(Arrays.asList(items));
}
static <T> EnhancedCollection<T> empty() {
return new SimpleEnhancedCollection<>(Collections.emptyList());
}
// 私有方法 (Java 9+) - 辅助默认方法
private void logOperation(String operation) {
System.out.println("执行操作: " + operation);
}
}
// 简单实现
class SimpleEnhancedCollection<T> implements EnhancedCollection<T> {
private final List<T> items;
public SimpleEnhancedCollection(List<T> items) {
this.items = new ArrayList<>(items);
}
@Override
public List<T> getItems() {
return items;
}
// 可以重写默认方法
@Override
public int size() {
System.out.println("自定义size方法");
return items.size();
}
}
// 使用示例
public class InterfaceEnhancementsDemo {
public static void main(String[] args) {
System.out.println("=== 接口增强特性演示 ===");
// 1. 使用静态方法创建集合
EnhancedCollection<String> fruits = EnhancedCollection.of("苹果", "香蕉", "橙子", "葡萄");
System.out.println("水果数量: " + fruits.size());
System.out.println("是否为空: " + fruits.isEmpty());
// 2. 使用默认方法
System.out.println("\n所有水果:");
fruits.forEach(fruit -> System.out.println("- " + fruit));
// 3. 使用过滤功能
List<String> filteredFruits = fruits.filter(fruit -> fruit.contains("果"));
System.out.println("\n包含'果'的水果: " + filteredFruits);
// 4. 空集合
EnhancedCollection<String> empty = EnhancedCollection.empty();
System.out.println("\n空集合大小: " + empty.size());
}
}
🔧 var关键字(Java 10+)
💻 局部变量类型推断
🎯 示例11:var关键字使用
import java.util.*;
import java.util.stream.Collectors;
public class VarKeywordDemo {
public static void main(String[] args) {
System.out.println("=== var关键字演示 ===");
// 1. 基本类型推断
System.out.println("\n1. 基本类型推断:");
var number = 42; // int
var text = "Hello World"; // String
var decimal = 3.14; // double
var flag = true; // boolean
System.out.println("number类型: " + ((Object)number).getClass().getSimpleName());
System.out.println("text类型: " + text.getClass().getSimpleName());
System.out.println("decimal类型: " + ((Object)decimal).getClass().getSimpleName());
System.out.println("flag类型: " + ((Object)flag).getClass().getSimpleName());
// 2. 集合类型推断
System.out.println("\n2. 集合类型推断:");
var list = new ArrayList<String>();
var map = new HashMap<String, Integer>();
var set = new HashSet<String>();
list.add("Java");
list.add("Python");
map.put("Java", 25);
map.put("Python", 30);
set.add("编程语言");
System.out.println("list: " + list);
System.out.println("map: " + map);
System.out.println("set: " + set);
// 3. 复杂表达式类型推断
System.out.println("\n3. 复杂表达式:");
var filteredList = list.stream()
.filter(lang -> lang.startsWith("J"))
.collect(Collectors.toList());
var upperCaseList = list.stream()
.map(String::toUpperCase)
.collect(Collectors.toList());
System.out.println("过滤后: " + filteredList);
System.out.println("大写后: " + upperCaseList);
// 4. 循环中使用var
System.out.println("\n4. 循环中使用var:");
var numbers = Arrays.asList(1, 2, 3, 4, 5);
for (var num : numbers) {
System.out.print(num + " ");
}
System.out.println();
// 5. var的限制
System.out.println("\n5. var使用注意事项:");
// ✅ 正确使用
var validExample = "这是有效的";
var anotherValid = new ArrayList<String>();
// ❌ 错误使用(这些会编译错误)
// var invalid; // 必须初始化
// var nullValue = null; // 不能推断null
// var lambda = x -> x * 2; // 不能推断lambda
// var array = {1, 2, 3}; // 不能推断数组字面量
System.out.println("var使用建议:");
System.out.println("- 在类型明显时使用,提高代码简洁性");
System.out.println("- 避免在类型不明确时使用,保持代码可读性");
System.out.println("- 主要用于局部变量,不能用于字段、方法参数或返回类型");
}
}
🔄 Switch表达式(Java 12+)
💻 增强的Switch语法
🎯 示例12:Switch表达式
public class SwitchExpressionDemo {
enum Day {
MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY, SUNDAY
}
enum Season {
SPRING, SUMMER, AUTUMN, WINTER
}
public static void main(String[] args) {
System.out.println("=== Switch表达式演示 ===");
// 1. 传统switch vs 新switch表达式
System.out.println("\n1. 语法对比:");
Day today = Day.FRIDAY;
// 传统switch语句
String dayType1;
switch (today) {
case MONDAY:
case TUESDAY:
case WEDNESDAY:
case THURSDAY:
case FRIDAY:
dayType1 = "工作日";
break;
case SATURDAY:
case SUNDAY:
dayType1 = "周末";
break;
default:
dayType1 = "未知";
}
System.out.println("传统switch: " + dayType1);
// 新switch表达式
String dayType2 = switch (today) {
case MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY -> "工作日";
case SATURDAY, SUNDAY -> "周末";
};
System.out.println("新switch表达式: " + dayType2);
// 2. 带yield的switch表达式
System.out.println("\n2. 使用yield:");
String description = switch (today) {
case MONDAY -> "周一,新的开始";
case FRIDAY -> "周五,即将周末";
case SATURDAY, SUNDAY -> {
String weekend = "周末";
yield weekend + ",休息时间";
}
default -> {
yield "普通的" + today.name().toLowerCase();
}
};
System.out.println("描述: " + description);
// 3. 实际应用示例
System.out.println("\n3. 实际应用:");
demonstrateCalculator();
demonstrateSeasonInfo();
}
// 计算器示例
public static void demonstrateCalculator() {
System.out.println("计算器示例:");
double result = calculate(10, 5, "+");
System.out.println("10 + 5 = " + result);
result = calculate(10, 5, "*");
System.out.println("10 * 5 = " + result);
result = calculate(10, 0, "/");
System.out.println("10 / 0 = " + result);
}
public static double calculate(double a, double b, String operator) {
return switch (operator) {
case "+" -> a + b;
case "-" -> a - b;
case "*" -> a * b;
case "/" -> {
if (b == 0) {
System.out.println("警告: 除数不能为0");
yield Double.NaN;
}
yield a / b;
}
case "%" -> a % b;
default -> {
System.out.println("不支持的操作符: " + operator);
yield Double.NaN;
}
};
}
// 季节信息示例
public static void demonstrateSeasonInfo() {
System.out.println("\n季节信息:");
for (Season season : Season.values()) {
String info = getSeasonInfo(season);
System.out.println(season + ": " + info);
}
}
public static String getSeasonInfo(Season season) {
return switch (season) {
case SPRING -> "春天,万物复苏,气温回暖";
case SUMMER -> "夏天,炎热多雨,适合游泳";
case AUTUMN -> "秋天,天高气爽,收获季节";
case WINTER -> "冬天,寒冷干燥,注意保暖";
};
}
}
🎯 综合实战练习
📊 练习1:函数式编程数据处理器 ⭐⭐⭐⭐
📝 练习描述
使用Lambda表达式和Stream API构建一个数据处理系统,支持复杂的数据查询、统计和转换操作。
🎯 学习目标
- 熟练运用Lambda表达式
- 掌握Stream API的高级用法
- 理解函数式编程思想
- 学会设计流畅的API
📋 具体要求
基础要求:
- 支持多种数据源(文件、数据库、API)
- 提供丰富的过滤和转换操作
- 实现数据统计和聚合功能
- 支持自定义处理函数
进阶要求:
5. 支持并行处理提升性能
6. 实现数据缓存机制
7. 提供数据验证和清洗功能
8. 支持多种输出格式
💡 实现提示
public class DataProcessor<T> {
private final Stream<T> dataStream;
public static <T> DataProcessor<T> of(Collection<T> data) {
return new DataProcessor<>(data.stream());
}
public <R> DataProcessor<R> map(Function<T, R> mapper) {
return new DataProcessor<>(dataStream.map(mapper));
}
public DataProcessor<T> filter(Predicate<T> predicate) {
return new DataProcessor<>(dataStream.filter(predicate));
}
public <K> Map<K, List<T>> groupBy(Function<T, K> classifier) {
return dataStream.collect(Collectors.groupingBy(classifier));
}
}
⏰ 练习2:现代化日期时间管理系统 ⭐⭐⭐⭐
📝 练习描述
使用新的日期时间API构建一个完整的时间管理系统,支持多时区、定时任务和时间计算。
🎯 学习目标
- 掌握新日期时间API的使用
- 理解时区处理机制
- 学会时间间隔计算
- 掌握日期格式化和解析
📋 具体要求
基础要求:
- 支持多时区时间显示和转换
- 实现定时任务调度功能
- 提供时间间隔计算工具
- 支持多种日期格式
进阶要求:
5. 实现工作日计算(排除节假日)
6. 支持重复事件的时间计算
7. 提供时间统计和分析功能
8. 支持时间数据的导入导出
🔧 练习3:Optional最佳实践重构 ⭐⭐⭐
📝 练习描述
将传统的null检查代码重构为使用Optional的现代化代码,提升代码的安全性和可读性。
🎯 学习目标
- 掌握Optional的正确使用方式
- 学会重构遗留代码
- 理解函数式编程的优势
- 提升代码质量
📋 具体要求
基础要求:
- 识别和重构null检查代码
- 使用Optional链式操作
- 实现安全的数据访问
- 提供默认值处理机制
进阶要求:
5. 设计Optional友好的API
6. 实现复杂的条件逻辑
7. 优化性能和内存使用
8. 编写完整的测试用例
✅ 完成标准
🎯 基础完成标准
- 正确使用Lambda表达式和方法引用
- 熟练运用Stream API进行数据处理
- 掌握新日期时间API的核心功能
- 理解Optional的使用场景和最佳实践
- 代码风格符合现代Java规范
🚀 进阶完成标准
- 能够设计函数式风格的API
- 性能优化合理,充分利用并行流
- 错误处理优雅,使用Optional避免NPE
- 代码可读性高,充分利用新特性简化逻辑
- 通过完整的单元测试验证
🏆 专家级标准
- 深入理解函数式编程思想
- 能够在实际项目中推广新特性使用
- 设计出优雅且高效的解决方案
- 具备重构遗留代码的能力
- 能够指导团队使用现代Java特性
📝 本章小结
🎯 核心知识点回顾
🔗 Lambda表达式与函数式编程
- ✅ 掌握Lambda表达式的语法和使用场景
- ✅ 理解函数式接口和方法引用
- ✅ 学会函数组合和高阶函数
- ✅ 熟练使用内置函数式接口
🌊 Stream API
- ✅ 掌握Stream的创建和基本操作
- ✅ 熟练使用中间操作和终端操作
- ✅ 理解并行流的使用和性能优化
- ✅ 掌握复杂的数据处理和统计操作
⏰ 新日期时间API
- ✅ 掌握LocalDate、LocalTime、LocalDateTime的使用
- ✅ 理解时区处理和ZonedDateTime
- ✅ 熟练进行日期计算和格式化
- ✅ 掌握Period和Duration的时间间隔计算
🔧 Optional类
- ✅ 理解Optional的设计目的和使用场景
- ✅ 掌握Optional的创建和基本操作
- ✅ 熟练使用map、flatMap、filter等方法
- ✅ 学会Optional与Stream的结合使用
📦 模块化系统
- ✅ 理解模块化的概念和优势
- ✅ 掌握module-info.java的编写
- ✅ 学会模块间的依赖管理
- ✅ 了解模块化项目的构建和部署
🆕 其他新特性
- ✅ 掌握接口的默认方法和静态方法
- ✅ 理解var关键字的使用和限制
- ✅ 熟练使用Switch表达式
- ✅ 了解Java版本演进和新特性趋势
📈 学习成果检验
🎯 自我检测清单
- 能够使用Lambda表达式简化代码
- 熟练运用Stream API处理集合数据
- 掌握新日期时间API替代传统Date类
- 正确使用Optional避免空指针异常
- 理解模块化系统的基本概念
- 了解Java新版本的重要特性
🚀 进阶学习方向
| 方向 | 内容 | 推荐资源 |
|---|---|---|
| 🔧 函数式编程深入 | Vavr库、响应式编程 | RxJava、Project Reactor |
| 🌊 大数据处理 | 并行计算、分布式处理 | Apache Spark、Flink |
| ⏰ 时间处理进阶 | 复杂时区、历法系统 | Joda-Time迁移指南 |
| 📦 模块化实践 | 大型项目模块化、OSGi | Spring Boot模块化 |
🗺️ 专栏学习路径图
📈 Java程序员从0到1成长路径
🎯 第一阶段:Java基础入门 (4-6周) - ✅ 已完成
┌─────────────┐ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐
│ 1.开发环境 │───▶│ 2.基础语法 │───▶│ 3.面向对象 │───▶│ 4.核心API │
│ 搭建 │ │ │ │ 编程基础 │ │ │
│ ✅ 已完成 │ │ ✅ 已完成 │ │ ✅ 已完成 │ │ ✅ 已完成 │
└─────────────┘ └─────────────┘ └─────────────┘ └─────────────┘
🚀 第二阶段:Java进阶技能 (4-6周)
┌─────────────┐ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐
│ 1.高级特性 │ │ 2.I/O与网络 │ │ 3.新特性 │ │ 4.工具框架 │
│ │ │ 编程 │ │ │ │ 入门 │
│ ✅ 已完成 │ │ ✅ 已完成 │ │ ✅ 已完成 │ │ 🎯 下一步 │
└─────────────┘ └─────────────┘ └─────────────┘ └─────────────┘
🎓 第三阶段:企业级开发 (6-8周)
┌─────────────┐ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐
│ 1.Spring │ │ 2.数据库 │ │ 3.Web开发 │ │ 4.微服务 │
│ 框架 │ │ 技术 │ │ │ │ 架构 │
│ 📅 计划中 │ │ 📅 计划中 │ │ 📅 计划中 │ │ 📅 计划中 │
└─────────────┘ └─────────────┘ └─────────────┘ └─────────────┘
📊 第二阶段详细进度
| 章节 | 主要内容 | 预计时间 | 难度 | 状态 |
|---|---|---|---|---|
| 🔧 1.Java高级特性 | 泛型、反射、注解、枚举 | 1-2周 | ⭐⭐⭐⭐ | ✅ 已完成 |
| 📁 2.I/O与网络编程 | 文件操作、网络通信、多线程 | 1-2周 | ⭐⭐⭐⭐ | ✅ 已完成 |
| 🆕 3.Java新特性 | Lambda、Stream API、新日期API | 1周 | ⭐⭐⭐⭐ | ✅ 已完成 |
| 🛠️ 4.工具与框架入门 | Maven/Gradle、JUnit、日志框架 | 1周 | ⭐⭐⭐ | 🎯 下一步 |
• 第二阶段进度:75% (3/4章节完成)
• 下一步:学习常用工具与框架入门
• 建议:巩固新特性知识,准备学习开发工具链
• 重点:掌握Maven构建工具、JUnit测试框架和日志系统
🎬 下一章预告
🛠️ 第二阶段第4章:常用工具与框架入门
🎯 下章学习内容
- 🏗️ Maven/Gradle构建工具详解
- 🧪 JUnit单元测试框架
- 📝 Log4j/SLF4J日志框架
- 🔧 开发工具链最佳实践
💡 学习建议
- 理解现代Java项目的构建流程
- 掌握自动化测试的重要性
- 学会使用专业的开发工具
- 建立良好的开发习惯
🎉 恭喜完成Java新特性的学习!
你已经掌握了现代Java开发的核心特性,
包括函数式编程、Stream API、新日期时间API等重要内容,
这些技能将大大提升你的编程效率和代码质量!
继续保持学习的热情,向着Java专家的目标前进! 🚀
📧 有问题?欢迎在评论区讨论交流!
⭐ 觉得有用?别忘了点赞收藏!
🔄 继续关注,更多精彩内容即将到来!





