1. Java学习Day16:从基础到进阶的关键跨越
作为一名从Java转Go又回到Java的老码农,我深知第16天往往是初学者从语法认知转向实际应用的分水岭。今天我们要突破的不仅是新的API,更是编程思维的升级——当你开始接触集合框架、异常处理和IO流时,才算真正触摸到Java企业级开发的门槛。
2. 集合框架:数据结构的Java实现
2.1 ArrayList与LinkedList的实战抉择
昨天我们学会了数组,今天ArrayList的出现会让你眼前一亮。但注意这个"动态数组"的扩容机制:
java复制// 默认初始容量10,扩容时newCapacity = oldCapacity + (oldCapacity >> 1)
List<Integer> list = new ArrayList<>();
for (int i = 0; i < 100; i++) {
list.add(i); // 第11次添加时触发第一次扩容
}
实际工程中建议在已知数据量时直接指定初始容量:
new ArrayList<>(1000),避免多次扩容损耗性能
LinkedList的节点式存储适合频繁插入删除的场景,但随机访问性能较差。我曾用JMH做过测试,在10万级数据量下:
- 头部插入:LinkedList比ArrayList快300倍
- 按索引查询:ArrayList比LinkedList快5000倍
2.2 HashMap的哈希碰撞解决方案
这个面试必问的知识点需要理解透:
java复制Map<String, Integer> map = new HashMap<>();
map.put("key1", 1);
// JDK8后的红黑树优化
for (int i = 0; i < 100; i++) {
map.put("key"+i, i); // 当链表长度>=8且数组长度>=64时转红黑树
}
调试时可以故意制造哈希碰撞:
System.out.println("Aa".hashCode() == "BB".hashCode()); // true
3. 异常处理的艺术
3.1 不要吞掉异常!
这是我见过最危险的坏习惯:
java复制try {
riskyOperation();
} catch (Exception e) {
e.printStackTrace(); // 这行代码价值百万美元!
}
正确的做法应该是:
- 记录完整堆栈(使用Log4j/SLF4J)
- 根据业务场景选择:
- 转换异常类型后抛出
- 重试机制(需设置最大重试次数)
- 熔断降级处理
3.2 自定义异常实践
在电商项目中,我这样设计业务异常:
java复制public class InventoryShortageException extends RuntimeException {
private final String sku;
private final int requested;
private final int available;
// 构造器包含业务上下文信息
public InventoryShortageException(String sku, int req, int avail) {
super(String.format("SKU %s shortage: request %d, available %d",
sku, req, avail));
this.sku = sku;
this.requested = req;
this.available = avail;
}
}
4. IO流:文件操作的基石
4.1 必须掌握的try-with-resources
对比两种写法:
java复制// 传统写法(容易忘记close)
FileInputStream fis = null;
try {
fis = new FileInputStream("test.txt");
// 操作流
} finally {
if (fis != null) fis.close();
}
// Java7+推荐写法(自动关闭资源)
try (FileInputStream fis = new FileInputStream("test.txt");
BufferedInputStream bis = new BufferedInputStream(fis)) {
// 操作流
}
4.2 NIO文件操作新姿势
Path和Files类让文件操作更优雅:
java复制Path path = Paths.get("data.log");
List<String> lines = Files.readAllLines(path, StandardCharsets.UTF_8);
// 遍历目录文件
try (Stream<Path> stream = Files.list(Paths.get("/tmp"))) {
stream.filter(Files::isRegularFile)
.map(Path::getFileName)
.forEach(System.out::println);
}
5. 环境配置避坑指南
5.1 Lombok编译器报错解决方案
遇到"you aren't using a compiler supported by lombok"时:
- 检查IDE的注解处理是否开启
- 在pom.xml中确认版本兼容性:
xml复制<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.30</version> <!-- 注意版本号 -->
<scope>provided</scope>
</dependency>
5.2 环境变量配置终极方案
推荐使用JEnv管理多版本JDK:
bash复制# 安装后切换版本
jenv add /Library/Java/JavaVirtualMachines/jdk-17.jdk/Contents/Home
jenv global 17
6. 面试八股文精要
6.1 HashMap高频考点
- 扩容机制:2的幂次方扩容(默认16→32→64...)
- 哈希计算:
(h = key.hashCode()) ^ (h >>> 16) - 线程安全替代方案:ConcurrentHashMap或Collections.synchronizedMap
6.2 ArrayList vs Vector
关键区别:
| 特性 | ArrayList | Vector |
|---|---|---|
| 线程安全 | 不安全 | 同步安全 |
| 扩容增量 | 50% | 100% |
| 迭代器 | fail-fast | fail-fast |
7. 明日学习路线建议
完成今天内容后,建议尝试:
- 用HashMap实现一个缓存系统(考虑LRU淘汰策略)
- 编写文件加密工具(结合IO流和加密算法)
- 实现自定义异常处理的订单系统
记得每天用git提交代码,我在学习时曾因没做版本控制丢失过三天的工作量。现在我的day16练习代码就托管在Gitee上,包含完整注释和测试用例
