Effective Java 3/E summary item 1 to 5 (Longer version)
22 Dec 2020You can find the shorter version of this summary here.
Item 1: Consider static factory methods instead of constructors
Pros:
- They have names
- Better readability (e.g. BigInteger’s static factory method
BigInteger.probablePrime) - Constructors have a signature conflict if parameter types and orders are the same - because all constructors are considered to have the same method name, but factory methods do not have this problem.
- Better readability (e.g. BigInteger’s static factory method
- They are not required to create a new object each time they are invoked.
- Can cache instances, or even never create an instance (e.g.
Boolean.valueOf)
- Can cache instances, or even never create an instance (e.g.
- They can return a subtype of their return type.
- The returned class can vary from call to call as a function of the input parameters.
- Better encapsulation (e.g., OpenJDK’s
EnumSethas two concrete implementations (RegularandJumbo) but clients do not have to care about them)
- Better encapsulation (e.g., OpenJDK’s
- The class of the returned object need not exist when the class containing the method is written (i.e., it can be injected later, such as using prototype pattern)
Cons:
- Classes without public or protected constructors cannot be subclassed.
- It is hard for programmers to find the static factory methods, compared to constructors - they do not stand out unless explicitly highlighted.
- Some common names include:
from,of,valueOf,getInstance,create,newInstanceetc.
- Some common names include:
Item 2: Consider a builder when faced with many constructor parameters
Constructors with too many parameters or options (telescoping constructor pattern), are hard to use and maintain. Consider a builder pattern to replace them. JavaBeans pattern could be considered as an alternative, but they preclude the possibility of making a class immutable.
Pros:
- Better readability
- Can ensure immutability
- Can be used repeatedly
Cons:
- Builder itself has a performance cost
- Builder pattern is more verbose. (it should be considered when there are enough parameters to make it worthwhile, say four or more.)
Item 3: Enforce the singleton property with a private constructor or an enum type
Notes:
-
Making a class a singleton can make it difficult to test.
-
Some consider singletons are an anti-pattern.
In this item, some non-lazy singleton generation techniques are illustrated with private constructor pattern or enum pattern. This is a well-studied topic, and the techniques include large code snippets, so I’ll not illustrate them in detail here.
The author encourages using the enum type as below.
This approach may feel a bit unnatural, but a single-element enum type is often the best way to implement a singleton.
Item 4: Enforce noninstantiability with a private constructor
When you have a utility class that should not be instantiated, provide a private constructor to prevent autogenerated public default constructor.
Pros:
- The instantiation is programmatically blocked.
- The class cannot be subclassed.
Cons:
- The class cannot be subclassed. (It is good and bad at the same time)
Item 5: Prefer dependency injection to hardwiring resources
Long story short, use interfaces instead of concrete classes (decouple classes) and inject dependencies instead of hardcoding them. If the code depends on the interface, the implementation’s change will affect the client much less than depending on the concrete implementations.