Create and destroy objects
1. Static factory method instead of constructor
When designing the instantiation method provided by the class, in addition to defining the public constructor, you can also consider providing a public static factory method
Benefits of using a static factory approach:
- Using static factory method can improve the readability of code, and the construction behavior of class can be described by method naming People who use your designed class can quickly know what object this method instantiates through the method name
For example:
public class Animal { private String name; public Animal(String name) { this.name = name; } // Through the method name, you can quickly know what kind of object instance to create public static Animal createCat() { return new Animal("Cat"); } public static Animal createDog() { return new Animal("Dog"); } }
- When you can control class instantiation, you don't have to create a new instance every time For example, singleton
- Using constructor to create an instance can only return itself, while static factory methods can return instances of subtypes, making instance creation more flexible
- When using static factory methods to create some generic classes, the code can be more concise
For example:
// JDK1. In the version before 7, the constructor is used to create the List set, and the generic related information behind the ArrayList cannot be omitted List<Map<String, String>> ls = new ArrayList<Map<String, String>>(); // Using the static factory method, you can simplify the amount of code. The static factory method of Lists in Guava List<Map<String, String>> list = Lists.newArrayList();
2. When the designed class has many fields, consider using builder
This is a form of Builder Pattern
public class NutritionInfo { // Required fields // Net content mL private final int netWeight; // optional field // Calories g private final int calories; // Fat g private final int fat; // Sodium mg private final int sodium; // Carbohydrate g private final int carbohydrate; public static class Builder { private final int netWeight; private int calories = 0; private int fat = 0; private int sodium = 0; private int carbohydrate = 0; public Builder(int netWeight) { this.netWeight = netWeight; } public Builder calories(int val) { calories = val; return this; } public Builder fat(int val) { fat = val; return this; } public Builder sodium(int val) { sodium = val; return this; } public Builder carbohydrate(int val) { carbohydrate = val; return this; } public NutritionInfo build() { return new NutritionInfo(this); } } private NutritionInfo(Builder builder) { netWeight = builder.netWeight; calories = builder.calories; fat = builder.fat; sodium = builder.sodium; carbohydrate = builder.carbohydrate; } }
Client call example:
// In this way, you can control that the netWeight field must be entered, and other nutrient fields can be set according to the actual situation NutritionInfo sodaWater = new NutritionInfo.Builder(330).sodium(12).build(); NutritionInfo cocaCola = new NutritionInfo.Builder(330).sodium(35).carbohydrate(27).calories(100).build();
3. Use private constructor and enum type to strengthen the attributes of singleton class
Use the private constructor or declare it as an enumeration class (starting from JDK1.5) to place the instantiation behavior inside the class to ensure that the uniqueness of the singleton cannot be destroyed outside
4. Use private constructor to strengthen the non instantiation of classes
Usage scenario: tool classes generally do not need to be instantiated. When writing a tool class, declare a private constructor
public class StringUtils { private StringUtils() {} // ... }
5. Avoid creating unnecessary objects
In general, it is better to reuse the same instance in the code instead of instantiating an object with the same function every time
If an object is immutable, it can always be reused
// Each call creates a new instance, and the parameter passed to the String constructor is also a String instance String s = new String("abc"); // Improved version String s1 = "abc";
6. Eliminate expired object references
public class Stack { private Object[] elemenets; private int size = 0; private static final int DEFAULT_INITIAL_CAPACITY = 16; public Stack() { elemenets = new Object[DEFAULT_INITIAL_CAPACITY]; } public void push(Object e) { ensureCapacity(); elemenets[size++] = e; } public Object pop() { if (size == 0) { throw new EmptyStackException(); } return elemenets[--size]; } private void ensureCapacity() { if (elemenets.length == size) { elemenets = Arrays.copyOf(elemenets, 2 * size + 1); } } }
Increasing the stack before shrinking will lead to memory leakage. Elements larger than size are not recycled, but remain in the array all the time