文章目录
- 第1部分 创建和销毁对象
- 一、前言
- 二、创建和销毁对象最佳实践内容
- 1. 优先使用工厂方法而非直接使用构造器
- 2. 避免创建不必要的对象
- 3. 避免使用过多的构造器
- 4. 避免使用原始类型(Raw Types)
- 5. 避免创建对象的过度依赖
- 6. 清理资源和关闭对象(显式地管理对象生命周期)
- 7. 避免使用 finalize()` 方法
- 三、小结
第1部分 创建和销毁对象
一、前言
《Effective Java》共有多个章节,每个章节提供了若干条建议或最佳实践,整理了对应章节关键的实践内容,用于自己后续代码开发过程中,参考对照,自查代码习惯,从而提升输出的代码质量。
二、创建和销毁对象最佳实践内容
1. 优先使用工厂方法而非直接使用构造器
- 原因:直接调用构造器来创建对象的方式灵活性较差,尤其是在构造过程中可能需要大量的复杂参数时,代码就会变得不易维护和阅读。
- 工厂方法的好处:工厂方法能够提供更高的灵活性,可以在方法内部控制对象的创建过程,并且可以对对象的创建方式进行封装。
- 示例:
// 使用构造器创建对象 Date date = new Date(2025, 1, 21);// 使用工厂方法创建对象 public static Date newInstance(int year, int month, int day) {return new Date(year, month, day); }
2. 避免创建不必要的对象
- 原因:频繁的对象创建会消耗更多的内存和处理时间,因此尽量避免无谓的对象实例化。
- 实践:例如,对于不可变的对象或常量,可以考虑使用单例模式、缓存技术或享元模式,来避免重复创建相同的对象。
- 示例:使用静态常量替代重复创建相同的对象。
// 不必要的对象创建 String a = new String("Hello");// 更好的做法 String b = "Hello"; // 直接使用字符串字面量
3. 避免使用过多的构造器
- 原因:过多的构造器会增加类的复杂性,并导致 API 不易使用,尤其是当类的构造器参数很多时,调用者很难确定需要传入哪些参数。
- 解决方法:使用 构建者模式(Builder Pattern) 来提供更清晰、更易于使用的构造方式。通过构建者模式,类的实例化变得更加灵活和可维护。
- 示例:使用构建者模式
public class NutritionFacts {private final int servings;private final int calories;public static class Builder {private final int servings;private int calories = 0;public Builder(int servings) {this.servings = servings;}public Builder calories(int val) {calories = val;return this;}public NutritionFacts build() {return new NutritionFacts(this);}}private NutritionFacts(Builder builder) {servings = builder.servings;calories = builder.calories;} }
4. 避免使用原始类型(Raw Types)
- 原因:原始类型会导致类型安全问题,并且不符合泛型的设计原则,因此应该避免使用原始类型。
- 实践:使用 Java 泛型来确保类型的安全性。
- 示例:避免原始类型
// 不安全的原始类型 List list = new ArrayList(); list.add("Hello");// 使用泛型 List<String> list = new ArrayList<>(); list.add("Hello");
5. 避免创建对象的过度依赖
- 原因:频繁地创建对象会导致内存占用增加、垃圾回收压力增大,甚至会影响性能。
- 实践:使用对象池、缓存等技术来重用对象,避免频繁的创建和销毁。
- 示例:
// 使用对象池技术可以避免频繁的创建和销毁对象 ObjectPool<Connection> pool = new ObjectPool<>(new ConnectionFactory()); Connection conn = pool.borrowObject();
6. 清理资源和关闭对象(显式地管理对象生命周期)
- 原因:如果对象占用系统资源(如数据库连接、文件句柄等),如果不手动关闭,会导致资源泄漏。
- 实践:使用
try-with-resources
或显式调用close()
方法来确保资源的正确释放。 - 示例:
// 使用 try-with-resources 自动关闭资源 try (BufferedReader br = new BufferedReader(new FileReader("file.txt"))) {// 处理文件 } catch (IOException e) {e.printStackTrace(); }
7. 避免使用 finalize()` 方法
- 原因:
finalize()
方法是在对象被垃圾回收器回收前调用的,但它的不确定性和执行时机会导致不可靠的资源释放。 - 实践:尽量避免使用
finalize()
,而是使用try-with-resources
或手动清理资源。 - 示例:
// 不推荐使用 finalize() 方法来管理资源 @Override protected void finalize() throws Throwable {try {// 资源清理代码} finally {super.finalize();} }
三、小结
在“创建和销毁对象”部分中,书中提出了许多关于如何高效、安全地创建和销毁对象的建议。使用工厂方法
、避免过度构造
、使用对象池
、清理资源
等方式,能够帮助程序员编写出更加健壮、性能优越
的 Java 程序。这些实践不仅有助于避免性能瓶颈,也使得代码更加清晰和易于维护。