Java coding notes I

  • Create a singleton by enum

A Singleton means a class can have one instance only (instantiated exactly once).

  1. The declaration will make it clear that the class is a singleton.
  2. It gives us the flexibility to change whether the class should be singleton without changing its API.

    public class Moose {
    public static final Moose INSTANCE = new Moose();
    private Moose() {...}
    public static Moose getInstance() { return INSTANCE;}
    }
  3. Making an enum type with one element

    // Enum singleton
    public enum Moose {
    INSTANCE;

    public void Move(){ ... }
    }

This approach is functionally equivalent to the public field approach.

  • Builder pattern for creating an object

In the case that a constructor has many parameters and it’s hard to remember the names.

Problem in JavaBeans pattern:

  1. A JavaBean may be in an inconsistent state partway through its construction.
  2. It precludes the possibility of making a class immutable.

Builder is a static member of the class.


public class StaffActionLog{
private final StaffMember staffMember;
private final DateTime date;
private String actionField;

private StaffActionLog(Builder builder){
this.staffMember = builder.staffMember;
this.actionField = builder.actionField;
this.date = builder.date;
}

//StaffActionLog builder
public static class Builder{
//mandatary fields
private final StaffMember staffMember;
//reserved field
private final DateTime date = new LocalDate().toDateTimeAtCurrentTime();
//optional fields
private String actionField;
//constructor for mandatory field
public Builder(StaffMember staffMember) {
this.staffMember = staffMember;
}
//setter method for option field
public Builder actionField(String actionField){
this.actionField = actionField;
return this;
}
//build() method, return the object
public StaffActionLog build(){
return new StaffActionLog(this);
}
}
}

Call the builder function

StaffActionLog staffActionLog = new StaffActionLog.Builder(staffMember).actionField(actionField).build();

  • Static factory method

Use static factory method instead of common constructor…

//static factory method for creating staff action log
public static StaffActionLog staticCreateStaffActionLog(StaffMember staffMember, String actionField, String oldValue, String newValue){
return new StaffActionLog.Builder(staffMember).actionField(actionField).oldValue(oldValue).newValue(newValue).build();
}

Why we use static factory method compared to the constructor?

  1. A readable name for the method to create an instance

    + Refer the static methods in class `java.util.concurrent.Executors` in JDK, such as `newFixedThreadPool`, `newSingleThreadExecutor`, `newCachedThreadPool`, and `newScheduledThreadPool` etc.
    
  2. Not required to create a new instance each time

    + It's possibly that the static method returns a instance existing in the cache rather than a new instance, which can improve the performance. E.g., static method for `Integer` in JDK, 
    
    public static Integer valueOf(int i) {
    assert IntegerCache.high >= 127;
    if (i >= IntegerCache.low && i <= IntegerCache.high)
    return IntegerCache.cache[i + (-IntegerCache.low)];
    return new Integer(i);
    }
    + The above code will return the `Integer` instances in the cache with high probability integers.
  3. Can return an object of any type

    + Return the instance of an inherited object, e.g., the application of `java.util.EnumSet` in JDK, 
    + In the following code, the `noneOf()` function will return an instance based on the parameters.
    
    public abstract class EnumSet<E extends Enum<E>> extends AbstractSet<E> implements Cloneable, java.io.Serializable {
    EnumSet(Class<E>elementType, Enum[] universe) {
    }
    public static <E extends Enum<E>> EnumSet<E> noneOf(Class<E> elementType) {
    if (universe.length <= 64)
    return new RegularEnumSet<>(elementType, universe);
    else
    return new JumboEnumSet<>(elementType, universe);
    }
    }
  4. Siplified the creation of a new object

    + Use this
    
    public static <K, V> HashMap<K, V> newInstance() {
    return new HashMap<K, V>();
    }
    Map<String, List<String>> m = HashMap.newInstance();
    Rather than
    Map<String, List<String>> m = new HashMap<String, List<String>>();

Disadvantages:

  1. With only static factory method, classes without public or protected constructors cannot be subclassed.
  2. The static factory methods are not readily distinguishable from other static methods.