1. Java基础语法回顾与提升
Java作为一门面向对象的编程语言,其基础语法是每个开发者必须掌握的基石。在"Java笔记2"这个系列中,我们将深入探讨Java编程中的核心概念和实用技巧。
1.1 变量与数据类型
Java是强类型语言,所有变量都必须先声明后使用。基本数据类型包括:
- 整型:byte(1字节)、short(2字节)、int(4字节)、long(8字节)
- 浮点型:float(4字节)、double(8字节)
- 字符型:char(2字节)
- 布尔型:boolean(1位)
在实际开发中,我建议:
- 优先使用int而非short/byte,除非有明确的内存优化需求
- 货币计算使用BigDecimal而非double
- 使用final修饰常量,命名全大写
java复制// 良好实践示例
final double TAX_RATE = 0.08;
BigDecimal price = new BigDecimal("19.99");
1.2 控制流程优化
控制语句是程序逻辑的骨架。除了基础的if-else、switch、for、while外,Java 8引入的Stream API提供了更优雅的处理方式:
java复制// 传统方式
List<String> filtered = new ArrayList<>();
for(String s : list) {
if(s.startsWith("A")) {
filtered.add(s.toUpperCase());
}
}
// Stream方式
List<String> filtered = list.stream()
.filter(s -> s.startsWith("A"))
.map(String::toUpperCase)
.collect(Collectors.toList());
提示:在复杂数据处理场景下,Stream API不仅代码更简洁,而且通过并行流(parallelStream)可以轻松实现并行处理。
2. 面向对象编程进阶
2.1 类与对象的设计原则
SOLID原则是面向对象设计的黄金准则:
- 单一职责原则(SRP)
- 开闭原则(OCP)
- 里氏替换原则(LSP)
- 接口隔离原则(ISP)
- 依赖倒置原则(DIP)
以单一职责原则为例,一个常见的反模式是"上帝类":
java复制// 违反SRP的示例
class Employee {
void calculateSalary() {...}
void saveToDatabase() {...}
void sendEmail() {...}
void generateReport() {...}
}
// 符合SRP的改进
class Employee {
void calculateSalary() {...}
}
class EmployeeRepository {
void save(Employee e) {...}
}
class EmailService {
void send(Employee e) {...}
}
class ReportGenerator {
void generate(Employee e) {...}
}
2.2 继承与组合的选择
很多开发者过度使用继承,实际上组合(Composition)通常是更好的选择:
java复制// 不推荐的继承方式
class Engine {
void start() {...}
}
class Car extends Engine { // Car不是Engine的特化
...
}
// 推荐的组合方式
class Car {
private Engine engine;
void start() {
engine.start();
}
}
3. Java集合框架深度解析
3.1 集合选型指南
Java集合框架主要分为:
- List:有序可重复
- ArrayList:随机访问快,插入删除慢
- LinkedList:插入删除快,随机访问慢
- Set:无序不重复
- HashSet:基于哈希表,O(1)时间复杂度
- TreeSet:基于红黑树,保持元素有序
- Map:键值对
- HashMap:常用实现
- LinkedHashMap:保持插入顺序
- TreeMap:按键排序
选择集合的经验法则:
- 需要快速查找?用HashSet/HashMap
- 需要保持插入顺序?用LinkedHashSet/LinkedHashMap
- 需要自然排序?用TreeSet/TreeMap
- 线程安全需求?考虑ConcurrentHashMap/CopyOnWriteArrayList
3.2 集合性能优化技巧
- 初始化时指定容量:
java复制// 不好:默认初始容量16,频繁扩容
Map<String, Integer> map = new HashMap<>();
// 好:预估元素数量
Map<String, Integer> map = new HashMap<>(expectedSize);
- 使用Arrays.asList()的陷阱:
java复制List<String> list = Arrays.asList("a", "b", "c");
list.add("d"); // 抛出UnsupportedOperationException
因为Arrays.asList()返回的是固定大小的列表。
4. 异常处理最佳实践
4.1 异常分类与处理策略
Java异常分为:
- 检查型异常(Checked Exception):必须处理
- 非检查型异常(Unchecked Exception):RuntimeException及其子类
- 错误(Error):系统级问题
处理原则:
- 不要捕获Throwable/Error
- 不要吞掉异常(空的catch块)
- 优先处理特定异常而非Exception
- 使用try-with-resources管理资源
java复制// 不好的做法
try {
// 可能抛出多种异常的代码
} catch (Exception e) {
// 吞掉所有异常
}
// 好的做法
try (InputStream is = new FileInputStream("file.txt")) {
// 使用资源
} catch (FileNotFoundException e) {
logger.error("文件未找到", e);
throw new BusinessException("文件处理失败", e);
} catch (IOException e) {
logger.error("IO异常", e);
throw new BusinessException("文件处理失败", e);
}
4.2 自定义异常设计
创建业务异常的建议:
- 继承RuntimeException而非Exception
- 提供有意义的错误信息
- 包含原始异常(cause)
- 定义错误码体系
java复制public class BusinessException extends RuntimeException {
private final ErrorCode errorCode;
public BusinessException(ErrorCode errorCode, String message) {
super(message);
this.errorCode = errorCode;
}
public BusinessException(ErrorCode errorCode, String message, Throwable cause) {
super(message, cause);
this.errorCode = errorCode;
}
// getter
}
5. Java 8+新特性实战
5.1 Lambda表达式与函数式编程
Lambda表达式使代码更简洁:
java复制// 传统匿名类
button.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
System.out.println("按钮点击");
}
});
// Lambda表达式
button.addActionListener(e -> System.out.println("按钮点击"));
常用函数式接口:
- Predicate
:断言,接受参数返回boolean - Function<T,R>:函数,接受T返回R
- Consumer
:消费者,接受T无返回 - Supplier
:提供者,无参数返回T
5.2 Stream API高级用法
收集器(Collectors)的强大功能:
java复制// 分组
Map<Department, List<Employee>> byDept = employees.stream()
.collect(Collectors.groupingBy(Employee::getDepartment));
// 分区
Map<Boolean, List<Employee>> partitioned = employees.stream()
.collect(Collectors.partitioningBy(e -> e.getSalary() > 5000));
// 连接字符串
String names = employees.stream()
.map(Employee::getName)
.collect(Collectors.joining(", "));
并行流注意事项:
- 确保操作是无状态的
- 避免共享可变状态
- 考虑排序需求(parallelStream会打乱顺序)
- 小数据集可能串行更快
6. 并发编程核心概念
6.1 线程基础与同步机制
创建线程的三种方式:
- 继承Thread类
- 实现Runnable接口
- 实现Callable接口+FutureTask
同步方式对比:
| 机制 | 优点 | 缺点 |
|---|---|---|
| synchronized | 简单, JVM内置支持 | 功能有限, 不可中断 |
| ReentrantLock | 可中断, 公平锁, 条件变量 | 需手动释放锁 |
| ReadWriteLock | 读写分离, 提高并发度 | 实现较复杂 |
| StampedLock | 乐观读, 更高性能 | API复杂, 容易出错 |
6.2 并发工具类实战
CountDownLatch示例:
java复制// 初始化计数器
CountDownLatch latch = new CountDownLatch(3);
// 工作线程
new Thread(() -> {
doWork();
latch.countDown();
}).start();
// 主线程等待
latch.await();
System.out.println("所有工作完成");
CompletableFuture异步编程:
java复制CompletableFuture.supplyAsync(() -> fetchData())
.thenApply(data -> processData(data))
.thenAccept(result -> saveResult(result))
.exceptionally(ex -> {
logger.error("处理失败", ex);
return null;
});
7. JVM基础与性能调优
7.1 内存模型与GC机制
JVM内存区域:
- 堆(Heap):对象实例
- 方法区(Method Area):类信息、常量
- 虚拟机栈(VM Stack):方法调用
- 本地方法栈(Native Stack)
- 程序计数器(PC Register)
常见GC算法:
- 标记-清除(Mark-Sweep)
- 标记-整理(Mark-Compact)
- 复制(Copying)
- 分代收集(Generational)
7.2 性能监控工具
常用命令行工具:
- jps:查看Java进程
- jstat:监控统计信息
- jmap:内存分析
- jstack:线程分析
- jcmd:多功能工具
可视化工具:
- VisualVM
- JConsole
- Mission Control(商业版)
8. 设计模式实战应用
8.1 创建型模式
单例模式的现代实现:
java复制public class Singleton {
private Singleton() {}
private static class Holder {
static final Singleton INSTANCE = new Singleton();
}
public static Singleton getInstance() {
return Holder.INSTANCE;
}
}
这种实现方式:
- 懒加载
- 线程安全
- 无同步开销
8.2 行为型模式
策略模式示例:
java复制interface DiscountStrategy {
BigDecimal applyDiscount(BigDecimal amount);
}
class RegularDiscount implements DiscountStrategy {
@Override
public BigDecimal applyDiscount(BigDecimal amount) {
return amount;
}
}
class VIPDiscount implements DiscountStrategy {
@Override
public BigDecimal applyDiscount(BigDecimal amount) {
return amount.multiply(BigDecimal.valueOf(0.9));
}
}
class Order {
private DiscountStrategy strategy;
void setStrategy(DiscountStrategy strategy) {
this.strategy = strategy;
}
BigDecimal checkout(BigDecimal amount) {
return strategy.applyDiscount(amount);
}
}
9. 单元测试与代码质量
9.1 JUnit 5新特性
JUnit 5的主要改进:
- 嵌套测试(@Nested)
- 参数化测试(@ParameterizedTest)
- 动态测试(@TestFactory)
- 扩展模型(Extension)
示例:
java复制@DisplayName("计算器测试")
class CalculatorTest {
private Calculator calculator = new Calculator();
@Nested
@DisplayName("加法测试")
class AddTest {
@ParameterizedTest
@CsvSource({"1,2,3", "0,0,0", "-1,1,0"})
void testAdd(int a, int b, int expected) {
assertEquals(expected, calculator.add(a, b));
}
}
}
9.2 Mockito高级用法
Mockito的BDD风格:
java复制@Test
void testOrderService() {
// Given
OrderRepository mockRepo = mock(OrderRepository.class);
OrderService service = new OrderService(mockRepo);
Order order = new Order("123");
given(mockRepo.findById("123")).willReturn(Optional.of(order));
// When
Order result = service.getOrder("123");
// Then
then(mockRepo).should().findById("123");
assertThat(result).isEqualTo(order);
}
10. 开发工具与效率提升
10.1 IDE高效使用技巧
IntelliJ IDEA快捷键:
- 重构:Shift+F6(重命名)、Ctrl+Alt+M(提取方法)
- 导航:Ctrl+N(类)、Ctrl+Shift+N(文件)
- 代码生成:Alt+Insert(getter/setter)
- 调试:F8(步过)、F7(步入)、Alt+F9(运行到光标)
10.2 构建工具进阶
Maven多模块项目结构:
code复制parent-project/
├── pom.xml
├── module-api/
│ └── pom.xml
├── module-service/
│ └── pom.xml
└── module-web/
└── pom.xml
依赖管理技巧:
- 使用dependencyManagement统一版本
- 用provided范围标记容器提供的依赖
- 用optional标记可选依赖
- 定期运行dependency:analyze检查无用依赖
11. 常见问题排查指南
11.1 内存泄漏诊断
常见内存泄漏场景:
- 静态集合持有对象
- 未关闭的资源(连接、流)
- 监听器未注销
- 线程池未关闭
诊断步骤:
- 使用jmap生成堆转储
- 用MAT分析内存占用
- 查找GC Roots到泄漏对象的引用链
11.2 死锁排查
死锁检测方法:
- jstack查看线程状态
- 查找BLOCKED状态和持有的锁
- 分析锁的获取顺序
预防措施:
- 按固定顺序获取锁
- 使用tryLock设置超时
- 减少同步代码块范围
12. 编码规范与代码审查
12.1 命名约定
包名:全小写,公司域名反写
java复制com.company.project.module
类名:大驼峰
java复制OrderService
方法名:小驼峰
java复制calculateTotalPrice()
常量:全大写,下划线分隔
java复制MAX_RETRY_COUNT
12.2 代码审查要点
审查清单:
- 是否遵循SOLID原则
- 异常处理是否恰当
- 是否有线程安全问题
- 性能是否有优化空间
- 测试覆盖率是否足够
- 是否有明显的代码坏味道
13. 新版本特性前瞻
13.1 Java 17新特性
- 密封类(Sealed Classes)
java复制public sealed class Shape
permits Circle, Square, Rectangle {...}
- 模式匹配switch(预览)
java复制String formatted = switch (obj) {
case Integer i -> String.format("int %d", i);
case String s -> String.format("String %s", s);
default -> obj.toString();
};
- 文本块改进
java复制String html = """
<html>
<body>
<p>Hello, world</p>
</body>
</html>
""";
13.2 Project Loom展望
虚拟线程(轻量级线程):
java复制try (var executor = Executors.newVirtualThreadPerTaskExecutor()) {
IntStream.range(0, 10_000).forEach(i -> {
executor.submit(() -> {
Thread.sleep(Duration.ofSeconds(1));
return i;
});
});
}
特点:
- 创建成本极低
- 数量可达百万级
- 由JVM调度,非OS线程
14. 项目实战经验分享
14.1 分层架构设计
典型三层架构:
- 表现层(Controller):处理HTTP请求
- 业务层(Service):核心业务逻辑
- 持久层(Repository):数据访问
我推荐的分包方式:
code复制com.company.project
├── config/ # 配置类
├── controller/ # 控制器
├── service/ # 服务接口
├── service/impl/ # 服务实现
├── repository/ # 仓储接口
├── entity/ # 实体类
├── dto/ # 数据传输对象
└── exception/ # 异常类
14.2 事务管理实践
声明式事务的陷阱:
java复制@Transactional
public void transfer(Account from, Account to, BigDecimal amount) {
withdraw(from, amount); // 内部调用
deposit(to, amount);
}
private void withdraw(Account account, BigDecimal amount) {
// 不生效,因为是通过this调用
}
解决方案:
- 自注入
java复制@Autowired
private TransferService self;
- 将方法移到另一个Service
- 使用AopContext.currentProxy()
15. 持续学习路线建议
Java开发者进阶路线:
- 核心基础:JVM、并发、集合
- 框架生态:Spring、Hibernate、MyBatis
- 分布式:微服务、缓存、消息队列
- 云原生:Docker、Kubernetes、Service Mesh
- 性能优化:JVM调优、数据库优化
- 架构设计:DDD、Clean Architecture
推荐学习资源:
- 书籍:《Effective Java》、《Java并发编程实战》
- 网站:InfoQ、DZone、Baeldung
- 视频:Pluralsight、极客时间
- 社区:GitHub、Stack Overflow、掘金
