1. Java基础语法回顾
作为一名Java开发者,我经常需要回顾基础语法要点。1月30日的笔记整理主要聚焦在以下几个核心概念上:
首先是数据类型和变量声明。Java是强类型语言,所有变量都必须先声明后使用。基本数据类型包括byte(1字节)、short(2字节)、int(4字节)、long(8字节)、float(4字节)、double(8字节)、char(2字节)和boolean(1位)。在实际编码中,我习惯用int处理整数运算,double处理浮点数,除非有明确的内存限制才会考虑使用更小的数据类型。
注意:使用float类型时一定要在数字后加f后缀,如float f = 3.14f,否则编译器会默认为double类型导致类型不匹配错误。
对象类型变量声明时需要特别注意初始化问题。比如String str;只是声明了引用变量,必须通过new String()或直接赋值才能使用,否则会抛出NullPointerException。这是我早期经常犯的错误之一。
2. 面向对象编程要点
Java作为纯粹的面向对象语言,其核心特性需要深入理解:
2.1 类与对象的关系
类是对象的模板,对象是类的实例。创建对象时,JVM会在堆内存中分配空间。构造方法的使用有几个要点:
- 如果没有显式定义构造方法,编译器会提供默认无参构造
- 一旦定义了任何构造方法,默认构造将不再自动提供
- 构造方法可以重载,通过参数列表区分
我常用的IDE快捷键是Alt+Insert(Windows/Linux)或Command+N(Mac)快速生成构造方法。
2.2 继承与多态
extends关键字实现继承,子类可以获得父类的非private成员。方法重写(Override)需要注意:
- 方法名、参数列表必须完全相同
- 返回类型可以是父类方法返回类型的子类
- 访问修饰符不能比父类更严格
- 不能抛出比父类方法更多的异常
多态的实现依赖于方法重写和父类引用指向子类对象。在实际项目中,我常用接口定义行为规范,抽象类提供部分实现,具体类完成最终实现。
3. 集合框架使用心得
Java集合框架是我日常开发中使用最频繁的API之一。根据不同的使用场景,我通常会这样选择集合类:
| 需求场景 | 推荐实现类 | 特点说明 |
|---|---|---|
| 快速随机访问 | ArrayList | 基于数组,查询快增删慢 |
| 频繁增删操作 | LinkedList | 基于链表,增删快查询慢 |
| 去重存储 | HashSet | 基于HashMap,无序 |
| 保持插入顺序 | LinkedHashSet | 链表维护插入顺序 |
| 自动排序 | TreeSet | 基于红黑树,自然排序 |
遍历集合时,我推荐使用Iterator或增强for循环,避免在遍历过程中直接修改集合导致ConcurrentModificationException。对于线程安全需求,优先考虑Collections.synchronizedXXX方法包装或直接使用Concurrent包下的并发集合类。
4. 异常处理最佳实践
Java的异常处理机制看似简单,但实际应用中容易踩坑。我的经验总结如下:
-
不要捕获Exception基类
应该捕获最具体的异常类型,避免隐藏真正的程序错误。例如处理文件IO时应该捕获IOException而非直接捕获Exception。 -
合理使用try-with-resources
对于实现了AutoCloseable接口的资源,使用try-with-resources语法可以自动关闭资源,代码更简洁安全:java复制try (BufferedReader br = new BufferedReader(new FileReader(path))) { return br.readLine(); } -
自定义异常的应用
在业务系统中,我习惯定义业务异常基类继承RuntimeException,然后派生出各种具体的业务异常。这样既保持了异常体系的清晰,又避免了到处声明throws的繁琐。 -
异常日志记录要点
记录异常时一定要包含完整的堆栈信息,我常用的日志模式是:java复制log.error("操作失败,参数:{}", param, e);其中e就是捕获的异常对象,日志框架会自动打印堆栈。
5. Java 8新特性实战
虽然Java已经发展到20+版本,但Java 8的特性仍然是企业开发的主流选择:
5.1 Lambda表达式
Lambda让代码更简洁,特别是在集合操作和事件处理中。我常用的几种形式:
java复制// 无参数
() -> System.out.println("Hello")
// 单参数
x -> x * x
// 多参数
(x, y) -> x + y
// 代码块
(name, age) -> {
String info = name + ":" + age;
System.out.println(info);
}
5.2 Stream API
Stream极大简化了集合处理,我的常用模式:
java复制List<String> filtered = list.stream()
.filter(s -> s.startsWith("A")) // 过滤
.map(String::toUpperCase) // 转换
.sorted() // 排序
.collect(Collectors.toList()); // 收集结果
提示:Stream操作分为中间操作和终止操作,只有遇到终止操作才会真正执行。要避免重复创建Stream,对同一数据源多次操作。
5.3 Optional类
用于优雅处理null值,减少NPE风险:
java复制Optional.ofNullable(user)
.map(User::getAddress)
.map(Address::getCity)
.orElse("默认城市");
6. 并发编程注意事项
Java并发编程是难点也是重点,我的经验教训包括:
-
线程创建
推荐使用线程池而非直接new Thread()。Executor框架提供了多种线程池实现:java复制ExecutorService pool = Executors.newFixedThreadPool(10); pool.submit(() -> {...}); -
线程安全集合
优先考虑ConcurrentHashMap、CopyOnWriteArrayList等并发集合,而非自行同步。 -
volatile关键字
保证变量可见性,但不保证原子性。适合作为状态标志使用。 -
锁的使用
ReentrantLock比synchronized更灵活,支持尝试获取锁、公平锁等特性:java复制Lock lock = new ReentrantLock(); if (lock.tryLock(1, TimeUnit.SECONDS)) { try { // 临界区代码 } finally { lock.unlock(); } } -
原子类
对于计数器等场景,AtomicInteger等原子类比同步代码块性能更好。
7. JVM基础与性能调优
理解JVM基本原理对写出高质量Java代码很有帮助:
7.1 内存区域
- 堆:对象实例存储区,GC主要工作区域
- 方法区:类信息、常量、静态变量
- 虚拟机栈:方法调用的栈帧
- 本地方法栈:Native方法调用
- 程序计数器:当前线程执行的字节码行号
7.2 GC调优实践
我常用的JVM参数:
code复制-Xms512m -Xmx512m // 堆初始和最大值设为相同避免动态调整
-XX:+UseG1GC // 启用G1收集器
-XX:MaxGCPauseMillis=200 // 目标最大GC停顿时间
通过jstat工具监控GC情况:
bash复制jstat -gcutil <pid> 1000 10
7.3 常见内存问题
- 内存泄漏:对象不再使用但仍被引用,无法回收
- OOM:堆内存不足,检查是否有内存泄漏或Xmx设置过小
- 频繁GC:对象创建/销毁过快,考虑对象池
8. 开发工具与技巧
8.1 IDE高效使用
IntelliJ IDEA是我的首选,几个实用技巧:
- 快速生成代码:Alt+Insert
- 提取方法:Ctrl+Alt+M
- 重构变量:Shift+F6
- 查看实现:Ctrl+Alt+B
- 最近文件:Ctrl+E
8.2 调试技巧
条件断点:右键断点设置条件
异常断点:捕获指定异常时暂停
远程调试:添加JVM参数
code复制-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=5005
8.3 构建工具
Maven依赖管理要点:
- 理解scope(compile/runtime/test等)
- 排除传递依赖
- 使用dependencyManagement统一版本
Gradle构建脚本比Maven更灵活,适合复杂项目。
9. 单元测试实践
好的单元测试应该:
- 快速执行(不依赖数据库/网络)
- 隔离性(测试之间不互相影响)
- 可重复(每次结果一致)
JUnit 5使用示例:
java复制@Test
@DisplayName("测试加法运算")
void testAdd() {
assertEquals(4, calculator.add(2, 2));
}
@ParameterizedTest
@ValueSource(ints = {1, 3, 5})
void testIsOdd(int number) {
assertTrue(number % 2 != 0);
}
Mockito模拟对象:
java复制List mockedList = mock(List.class);
when(mockedList.get(0)).thenReturn("first");
verify(mockedList).get(0);
10. 编码规范与设计原则
10.1 命名规范
- 类名:大驼峰,如UserService
- 方法名:小驼峰,如getUserName
- 常量:全大写加下划线,如MAX_SIZE
- 包名:全小写,反向域名,如com.example.project
10.2 设计原则
-
SOLID原则:
- 单一职责
- 开闭原则
- 里氏替换
- 接口隔离
- 依赖倒置
-
DRY原则:不要重复自己
-
KISS原则:保持简单
-
YAGNI原则:你不会需要它
10.3 设计模式应用
我常用的几种模式:
- 工厂模式:对象创建解耦
- 策略模式:算法替换
- 观察者模式:事件通知
- 装饰器模式:动态扩展功能
例如使用策略模式处理不同支付方式:
java复制interface PaymentStrategy {
void pay(int amount);
}
class CreditCardPayment implements PaymentStrategy {...}
class AlipayPayment implements PaymentStrategy {...}
class PaymentContext {
private PaymentStrategy strategy;
public void executePayment(int amount) {
strategy.pay(amount);
}
}
