# Effective Java Notes [On Hold]
[ToC]
## Introduction
These are my ongoing notes for Effective Java. **Note-taking is currently on hold to prioritize other reading material for work.**
## Chapter 2: Creating and Destroying Objects
### Item 1: Consider static factory methods instead of constructors
**Static factory method** = static method that returns an instance of a class
Naming Convention
* `from`: type conversion, takes parameter and returns corresponding instance of parameter
* `to`: aggregation method, takes multiple parameters and returns instance type that incorporates them
* `valueOf`: verbose alternative to `to` and `from`
* `instance`/`getInstance`: returns instance that is described by parameters
* `create`/`newInstance`: same as above, but returns a new instance
* `getType`: `getInstance` when factory method is in a different class
* `newType`: `newInstance` when factory method is in a different class
* `type`: concise alternative to `getType` and `newType`
**Advantages**
* names, which are more intuitive and easier to read than construtors
* new object is not created when invoked
* immutable classes can cache and re-use preconstructued instances, which can improve performance
* instance-controlled class: class that controls its number of instances
* return any object that is a subtype of the return type
* interface-based frameworks: interfaces provide natural return types for static factory methods
* class of returned object can vary based on parameters
* hides implementation -> concise API
* class of returned object does not need to exist when class containing the method is written
* service-provider frameworks: system that has providers implement a service and has the service make implementations available to clients
* service interface: implementation
* provider registration API: register implementation
* service access API: clients to obtain instances of services
* service provider interface: produces instances of service interface; optional
**Disadvantages**
* classes without public or protected constructors cannot be subclassed
* subclasses implicitly call the constructor of the superclass in their constructor; no access means this is impossible
* hard for programmers to find
* does not stand out in API documentation
### Item 2: Consider a builder when faced with many constructor parameters
Traditionally, classes with many constructor parameters use:
* **Telescoping constructor pattern**: provide a constructor with the necessary parameters, a contructor with one optional parameter, a constructor with two optional parameters, and so on until you get a constructor with all optional parameters
* doesn't scale well
* hard to read and write
* **JavaBeans pattern**: parameterless constructor and setter methods to set parameters
* more readable, but less safe
* JavaBean may end up in an inconsistent state partway through construction since there is no way to enforce consistency by checking constructor parameters
* cannot make a class immutable and harder to make thread-safe
**An alternative approach:**
**Builder pattern**: client calls constructor or static factory method with required parameters to get a builder object, calls builder's setter methods to set optional parameters, and paramaterless `build` method to generate a immutable object
* best of both worlds
* especially great for optional parameters or parameters with identical types
* check validity of parameters in builder's constructor and setter methods
* check invariants involving parameters in the constructor invoked by `build` after copying parameters from builder; failed check should throw `IllegalArgumentException`
* great for hierarchial structure
* *simulated self-type idiom*: method chaining in subclasses without casting
* *covariant return typing*: subclass method returns a subtype of the return type declared in the superclass; lets clients use builders without casting
* Advantages
* multiple varargs parameters
* aggregate parameters from multiple calls into a single field
* build multiple objects
* tweak parameters of builder between invocations of `build`
* fill in fields automatically on object creation
* Disadvantages
* performance cost from creating builder
* more verbose than telescoping constructor pattern; only use with 4 or more parameters or if you want to add more parameters in the future
### Item 3: Enforce the singleton property with a private constructor or an enum type
**Singleton**: class that is instantiated exactly once
* represent stateless object (e.x. a function) or a unique system component
* difficult to test because of mock implementation substitution
**Common implementations:**
* private constructor that is called once to intialize a public static final field that holds the instance
* To prevent an attack that invokes the private constructor reflectively, modify the constructor to throw an exception when creating a second instance
* API makes it clear that the class is a singleton
* same as above, except use a public static factory method to return the instance instead of a public field
* simpler than first implementation
* more flexibility to change class into a non-singleton implementation
* generic singleton factory
* method reference can be used as a supplier
* declare a single-element enum
* more concise than public field approach
* serialization mechanism
* best way to implement singleton
* can't use if singleton extends a superclass other than `Enum`
* Make a singleton class `Serializable`
* implement `Serializable`
* declare all instance fields `transient`
* `readResolve` method (prevents new instances from being created when a serialized instance is deserialized)
### Item 4: Enforce noninstantiability with a private constructor
**Static utility class** = only has static methods and fields
* Use cases: group related methods on primitive values and arrays, objects that implement an interface, final class (cannot be subclasses)
* should not be instantiated
* making a class abstract for noninstantiability does not work because class can be subclasses and subclass instantiated
* instead, make the constructor private, throw an assertion error inside the contructor to prevent it from being invoked in the class, and include a comment
* prevents subclasses as constructor cannot be invoked
### Item 5: Prefer dependency injection to hardwiring resources
* If the class relies on resources, use dependency injection pass the resource into the constructor when creating a new instance
* preserves immutability
* applicable to constructors, static factories, builders
* Variant: pass in resource factory to constructor (Factory Method pattern)
* `Supplier<T>` interface represents factories
* type parameter should be bounded wildcard type to allow client to pass in a factory (`Mosaic create(Supplier<? extends Tile> tileFactory) { ... }`)
* large projects with many dependencies should rely on a dependency injection framework such as Dagger, Guice, or Spring
### Item 6: Avoid creating unnecessary objects
* reuse a single object instead of creating a functionally equivalent object every time
* an immutable object can always be reused
* use static factory methods over constructors for immutable classes
* `Boolean.valueOf` vs `Boolean(string)`
**Example**
```
// Performance can be greatly improved!
static boolean isRomanNumeral(String s) {
return s.matches("^(?=.)M*(C[MD]|D?C{0,3})"
+ "(X[CL]|L?X{0,3})(I[XV]|V?I{0,3})$");
}
```
A new pattern instance is created every time this method is called. This is expensive since the regular expression will be compiled into a [finite state machine](https://stackoverflow.com/questions/525004/short-example-of-regular-expression-converted-to-a-state-machine).
```
// Reusing expensive object for improved performance
public class RomanNumerals {
private static final Pattern ROMAN = Pattern.compile(
"^(?=.)M*(C[MD]|D?C{0,3})"
+ "(X[CL]|L?X{0,3})(I[XV]|V?I{0,3})$");
static boolean isRomanNumeral(String s) {
return ROMAN.matcher(s).matches();
}
}
```
Instead, compile the pattern upon class initiatlization, cache it, and reuse the same instance over and over again.
* Lazy initialization = initialize a field when it is first used
* un-needed in the example because it is too complicated and has no measureable performance improvement
* adapter/view = objects that delegates to a backing object, providing an alternate interface,
* no need to create more than one instance of a given adapter to a given object
* Example: `keySet` method for `Map`
* Autoboxing = mix primitive types and objects
```
// Hideously slow! Can you spot the object creation?
private static long sum() {
Long sum = 0L;
for (long i = 0; i <= Integer.MAX_VALUE; i++)
sum += i;
return sum;
}
```
The program above is slow because it constructs unnecessary `Long` instances. Changing `Long` to `long` greatly reduces runtime.
* Takeaway: Prefer primitives to boxed primitives and watch out for unintentional autoboxing
* Not a hard rule. Creating and reclaiming small objects with constructors that do little work is relatively cheap and can increase readability
* Object pools are a bad idea unless the objects are extremely heavyweight
* Example: database connection, makes sense to reuse object for connection cost
* Drawbacks: code clutter, increased memory footprint, harms performance
* defensive copying requires making a new object, penalty for not doing this is greater than making a duplicate object -> bugs and security holes vs style and performance
### Item 7: Eliminate obsolete object references
In Java, objects are automatically re-claimed when you're done with them, but you still need to think about memory management
**Example**
```
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);
}
}
```
* Code has a memory leak. Objects popped off stack will not be garbage collected, even if the program does not have references to them, because the stack maintains obsolete references
* Results in performance decrease. Extreme cases cause disk paging + program failure
**Solution:**
```
public Object pop() {
if (size == 0)
throw new EmptyStackException();
Object result = elements[--size];
// Eliminate obsolete reference return result;
elements[size] = null;
}
```
* Null out references once they become obsolete
* Benefit is that an error will be caught if the references were de-refereneced by accident
* Nulling out every object reference clutters up the program unnecessarily
* Practice should be the exception, not the norm
* Best way is to let the variable that contained the reference to fall out of scope
* Whenever a class manages its own memory, look for memory leaks
* Example: `Stack` class has storage pool for elements of the `elements` array. Active portion elements are allocated and remainder of free, but garbage collector cannot differentiate between the two. Therefore, programmer must null free references.
* Cache = common source of memory leak
* Solutions
* Represent cache as `WeakHashMap` = entries removed after becoming obsolete, desired lifetime of entires determined by external references to key, not value
* If cache entry lifetime is not well defined + entries are less valuable over time = cleanse cache of unused entries using a background thread or when adding new entries to cache
* Listeners and other callbacks = another source of memory leak
* store only weak references to callbacks such as cache entries in a `WeakHashMap`
* heap profilers can be used to identify memory leaks
### Item 8: Avoid finalizers and cleaners
* Finalizers and Cleaners: release resources used by objects before they're removed from memory
* finalizers are dangerous, unpredictable, unnecessary
* finalizers [deprecated](https://bugs.openjdk.java.net/browse/JDK-8165641) in Java 9 for cleaners, which are less dangerous, but still unpredictable and unncessary
### Item 9: Prefer try-with-resources to try-finally
* Libraries have resources that must be manually closed using a `close` method: `InputStream`, `OutputStream`, etc.
* Historically, try-finally statments were used, but they have deficiencies and are messy
Example:
```
static void copy(String src, String dst) throws IOException {
InputStream in = new FileInputStream(src);
try {
OutputStream out = new FileOutputStream(dst);
try {
byte[] buf = new byte[BUFFER_SIZE];
int n;
while ((n = in.read(buf)) >= 0)
out.write(buf, 0, n);
} finally {
out.close();
}
} finally {
in.close();
}
}
```
* try-with-resource statement must have resources that implement `AutoCloseable` interface (any resource that must be closed needs to implement this)
* exceptions are also suppressed to get the original exception
* shorter, cleaner code
Example
```
static void copy(String src, String dst) throws IOException {
try (InputStream in = new FileInputStream(src);
OutputStream out = new FileOutputStream(dst)) {
byte[] buf = new byte[BUFFER_SIZE];
int n;
while ((n = in.read(buf)) >= 0)
out.write(buf, 0, n);
}
}
```
## Chapter 3: Methods Common to All Objects
### Item 10: Obey the general contract with overriding equals
* Don't override the equals method if each instance of the class is inherently unique
* No need for a class to provide a logical equality test, superclass has overriden equals and superclass behavior is appropriate for this class, class is private/package-private and equals method will never be invoked
**Equals Method**
```
@Override
public boolean equals(Object o) {
throw new AssertionError(); // Method is never called
}
```
* Override equals when class has a different notion of logical equality and a superclass has not overriden equals
* Occurs for value classes, which represent a value such as `Integer` and `String`
* Exceptions are value classes that use instance control or enum types
* The equals method implements an equivalence relation with these properties:
* Reflexive: For any non-null reference value `x`, `x.equals(x)` returns true
* Symmetric: For any non-null reference values x and y, `x.equals(y)` must return true if and only if `y.equals(x)` returns true.
* Transitive: For any non-null reference values `x`,`y`,`z`,if `x.equals(y)` returns true and `y.equals(z)` returns true, then `x.equals(z)` must return true.
* Consistent: For any non-null reference values `x` and `y`, multiple invocations of `x.equals(y)` must consistently return true or consistently return false, provided no information used in equals comparisons is modified.
* For any non-null reference value `x`,`x.equals(null)` must return false.
**Final notes:**
* Always override hashcode when overriding equals
* Don't substitute another type for object in the equals declaration
### Item 11: Always override `hashcode` when you override `equals`
* Not overriding `hashCode` will prevent it from working in collections such as `HashMap` and `HashSet` because equal objects must have equal hashcodes
* Good hash code produces unequal hashcodes for unequal instances
* If class is immutable and cost of calculating hashcode is significant, consider caching it or lazily initialize the first time `hashCode` is called
* Don't exclude significant fields from hashcode to improve performance
* Don't provide detailed specifications for value returned by hashcode so there's more flexibility to change it
### Item 12: Always override `toString`
* a good `toString` implementation makes class more pleasant to use and easier to debug
* `toString` method should return all interesting information contained in object
* specifying format of return value in documentation
### Item 13: Override `clone` judiciously
* `Cloneable` meant to be mixin interface, but it works counterintuitively because it has no methods, meaning it lacks a `clone` method. Object's `clone` method is protected.
* If a class implements `Cloneable`, Object's `clone` method returns a field-by-field copy of the object
* In practice, a class implementing Cloneable is expected to provide a properly functioning public clone method
* immutable classes should not provide a `clone` method
* new interfaces and classes should not extend `Cloneable`
* less harmful for final classes, but only do so for justified reasons
### Item 14: Consider implementing `Comparable`
* `compareTo` method is available in `Comparable` and is not declared in `Object`
* used for order comparisions
* returns negative value for less than, 0 for equal, and positive value for greater than
* throws `ClassCastException` when objects are of different type
* implementing `Comparable` implies that instances of a class have a natural ordering
* all value classes + enums implement `Comparable`
* When writing `compareTo` methods for integral primitive fields, use `compare` method instead of relational operators because the latter is considered verbose and error-prone
* `Comparator` interface has comparator construction methods, which is more concise, but has a minor performance cost
## Chapter 4: Classes and Interfaces
TBD
## Sources
Effective Java by Joshua Bloch