第1条:考虑用静态工厂方法代替构造器:
public class Services { private Services() { } // Prevents instantiation (Item 4) // Maps service names to services private static final Map<String, Provider> providers = new ConcurrentHashMap<String, Provider>(); public static final String DEFAULT_PROVIDER_NAME = "<def>"; // Provider registration API public static void registerDefaultProvider(Provider p) { registerProvider(DEFAULT_PROVIDER_NAME, p); } public static void registerProvider(String name, Provider p) { providers.put(name, p); } // Service access API public static Service newInstance() { return newInstance(DEFAULT_PROVIDER_NAME); } public static Service newInstance(String name) { Provider p = providers.get(name); if (p == null) throw new IllegalArgumentException( "No provider registered with name: " + name); return p.newService(); } }
第2条:遇到多个构造器参数时要考虑用构建器builder:
public class NutritionFacts { private final int servingSize; private final int servings; private final int calories; private final int fat; private final int sodium; private final int carbohydrate; public static class Builder { // Required parameters private final int servingSize; private final int servings; // Optional parameters - initialized to default values private int calories = 0; private int fat = 0; private int carbohydrate = 0; private int sodium = 0; public Builder(int servingSize, int servings) { this.servingSize = servingSize; this.servings = servings; } public Builder calories(int val) { calories = val; return this; } public Builder fat(int val) { fat = val; return this; } public Builder carbohydrate(int val) { carbohydrate = val; return this; } public Builder sodium(int val) { sodium = val; return this; } public NutritionFacts build() { return new NutritionFacts(this); } } private NutritionFacts(Builder builder) { servingSize = builder.servingSize; servings = builder.servings; calories = builder.calories; fat = builder.fat; sodium = builder.sodium; carbohydrate = builder.carbohydrate; } public static void main(String[] args) { NutritionFacts cocaCola = new NutritionFacts.Builder(240, 8) .calories(100).sodium(35).carbohydrate(27).build(); } }
第3条:用私有构造器或者枚举类型强化Singleton属性:
从Java 1.5发行版开始,实现Singleton的最佳实践方法是,编写一个包含单个元素的枚举类型:
public enum Elvis { INSTANCE; public void leaveTheBuilding() { System.out.println("Whoa baby, I'm outta here!"); } // This code would normally appear outside the class! public static void main(String[] args) { Elvis elvis = Elvis.INSTANCE; elvis.leaveTheBuilding(); } }
第4条:通过私有构造器强化不可实例化的能力:
// Noninstantiable utility class public class UtilityClass { // Suppress default constructor for noninstantiability private UtilityClass() { throw new AssertionError(); } }
第5条:避免创建不必要的对象:
除了重用不可变对象外,也可以重用那些已知不会被修改的可变对象。
class Person { private final Date birthDate; public Person(Date birthDate) { // Defensive copy - see Item 39 this.birthDate = new Date(birthDate.getTime()); } // Other fields, methods /** * The starting and ending dates of the baby boom. */ private static final Date BOOM_START; private static final Date BOOM_END; static { Calendar gmtCal = Calendar.getInstance(TimeZone.getTimeZone("GMT")); gmtCal.set(1946, Calendar.JANUARY, 1, 0, 0, 0); BOOM_START = gmtCal.getTime(); gmtCal.set(1965, Calendar.JANUARY, 1, 0, 0, 0); BOOM_END = gmtCal.getTime(); } public boolean isBabyBoomer() { return birthDate.compareTo(BOOM_START) >= 0 && birthDate.compareTo(BOOM_END) < 0; } }
第6条:消除过期的对象引用:
内存泄露的一个典型例子:
public class Stack { private Object[] elements; private int size = 0; private static final int DEFAULT_INITIAL_CAPACITY = 16; public Stack() { elements = new Object[DEFAULT_INITIAL_CAPACITY]; } public void push(Object e) { ensureCapacity(); elements[size++] = e; } public Object pop() { if (size == 0) throw new EmptyStackException(); return elements[--size]; } /** * Ensure space for at least one more element, roughly doubling the capacity * each time the array needs to grow. */ private void ensureCapacity() { if (elements.length == size) elements = Arrays.copyOf(elements, 2 * size + 1); } }
从栈中弹出来的对象不会当做垃圾回收,因为栈内部维护着这些对象的过期引用(obsolete reference),所谓的过期引用,是指永远不会再被解除的引用。本例中,凡是elements数组的活动部分之外的任何引用都是过期的,活动部分是指elements中下标小于size的那些元素。
pop方法的修订版:
public Object pop() { if(size == 0) throw new EmptyStackException(); Object result = elements[--size]; elements[size] = null; // Eliminate obsolete reference return result; }
一般而言,只要类是自己管理内存,程序员就应该警惕内存泄露问题,一旦元素被释放掉,则该元素中包含的任何对象引用都应该被清空。
内存泄露的另一个来源是缓存。
内存泄露的第三个来源是监听器和其他回调。确保回调立即被当做垃圾回收的最佳方法是只保留它们的弱引用 weak reference,例如,只将它们保存成WeakHashMap中的key
第7条:避免使用终结方法finalizer:
finalizer通常是不可预测的,也是很危险的,一般情况下是不必要的。会导致不稳定,性能降低,不可移植。
本人博客已搬家,新地址为:http://yidao620c.github.io/
相关推荐
### 第二章 创建和销毁对象 这一章深入探讨了对象的生命周期管理,包括: 1. **静态工厂方法**:相比构造器,静态工厂方法有优点如可以不返回新实例、允许返回同一实例(单例)、可以有更具选择性的访问控制,并且...
在 Java 中,创建和销毁对象是非常重要的。静态工厂方法可以代替构造器,提供了更多的灵活性和性能优势。静态工厂方法可以返回原类型的任何子类型,且可以将构建好的实例缓存起来,方便重复利用,不用每次调用都创建...
1. **第2章 创建和销毁对象** - 单例模式:讲解了如何正确实现单例类,避免多线程环境下的并发问题。 - 构造函数:强调构造函数应简洁,避免在构造过程中执行复杂操作。 - 工厂方法:介绍工厂方法模式,作为创建...
创建和销毁对象 考虑使用静态工厂方法代替构造方法 优点: 有名字 每次调用的时候,不一定要创建新的对象 可以返回一个类型的子类型 Collections就是这种用法 返回对象的类可以随调用的不同而变化(用输入的参数值...
书中的一些关键知识点可能包括:理解对象的创建和销毁、接口设计、类设计、方法设计、泛型的使用、异常处理、并发编程、Java集合框架的使用和扩展等等。在学习这些内容时,读者将被引导深入理解Java语言的细节,并...
目录:一、创建和销毁对象 (1 ~ 7)二、对于所有对象都通用的方法 (8 ~ 12)三、类和接口 (13 ~ 22)四、泛型 (23 ~ 29)五、枚举和注解 (30 ~ 37)六、方法 (38 ~ 44)七、通用程序设计 (45 ~ 56)八、异常 ...
创建和销毁对象 03 - 所有对象通用的方法 04 - 类和接口 05 - 泛型 06 - 枚举和注释 07 - Lambda 和流 08 - 方法 09 - 通用编程 10 - 例外 11 - 并发 12 - 序列化 第 2 章 - 创建和销毁对象 第 1 项 - 考虑静态工厂...
创建和销毁对象 1.使用静态工厂方法而不是构造函数 好处 与构造函数不同,它们有名称 与构造函数不同,它们不需要在每次调用时都创建一个新对象 与构造函数不同,它们可以返回其返回类型的任何子类型的对象 它们减少...
#### 第二章 创建/销毁对象 ##### 用静态工厂方法代替构造器 在面向对象编程中,对象的创建通常是通过构造器来完成的。然而,在某些情况下,使用静态工厂方法来创建对象可能会更加灵活和高效。 **静态工厂方法的...
第2章对象的创建和销毁 项目编号 标题 副标题 经理 项目1 项目2 项目3 项目4 项目5 不要直接指定资源,请使用依赖对象注入 莉娜 项目6 避免不必要的对象创建 德玛 项目7 释放使用的对象参考 莉娜 项目8 避免使用...
通过以上对“Effective Java 中文版 第二版”的核心知识点的总结,我们可以看到这本书覆盖了Java编程语言的各个方面,包括面向对象设计原则、类与接口的设计、对象的创建与销毁、枚举类型与注解、泛型与集合框架以及...
章:创建和销毁对象 第 1 条:考虑静态工厂方法而不是构造函数 由于以下原因,最好使用静态工厂而不是构造函数: 它们的名称可以帮助识别静态构造函数的操作 不需要返回新对象,您可以控制何时以及是否需要返回新...
2. **类与对象**:Java是一种面向对象的语言,理解类的定义、对象的创建与销毁、封装、继承、多态等概念至关重要。同时,深入探讨构造函数、访问修饰符、抽象类与接口的应用。 3. **异常处理**:Java中的try-catch-...
final、finally、finalize三者区别:final用于声明常量,finally用在try-catch-finally语句中表示必须执行的代码块,finalize是Object类的一个方法,垃圾回收器在销毁对象之前会调用它。 Io流的层次结构:Java中Io...
- **线程池**:通过管理一组预先创建好的线程来提高性能,避免频繁创建和销毁线程的开销。 - **不可变对象**:使用不可变对象可以避免并发修改问题,因为一旦创建后其状态就不能改变。 #### 七、本书内容概览 第一...
这种模式在需要频繁创建和销毁对象的场景中尤其有用,因为它可以节省系统资源并确保对象间的协调一致。以下是Java实现的六种单例模式的详细解释: 1. 懒汉式(Lazy Initialization): 这种方式延迟了单例对象的...
#### 二、创建与销毁对象 ##### Item1:考虑提供静态工厂方法而不是构造器 - **目的**:简化对象创建过程,提高代码的可读性和可维护性。 - **实现方式**: - 定义一个静态方法来创建对象,而非直接使用构造器。 -...