More on this book
Community
Kindle Notes & Highlights
The Liskov substitution principle says that any important property of a type should also hold for all its subtypes so that any method written for the type should work equally well on its subtypes
While there is no satisfactory way to extend an instantiable class and add a value component, there is a fine workaround: Follow the advice of Item 18, “Favor composition over inheritance.”
Whether or not a class is immutable, do not write an equals method that depends on unreliable resources. It’s
To avoid this sort of problem, equals methods should perform only deterministic computations on memory-resident objects.
An excellent alternative to writing and testing these methods manually is to use Google’s open source AutoValue framework, which automatically generates these methods for you, triggered by a single annotation on the class .
If a class is immutable and the cost of computing the hash code is significant, you might consider caching the hash code in the object rather than recalculating it each time it is requested.
A notable exception to this rule is arrays, which are best copied with the clone method.
Use of the relational operators < and > in compareTo methods is verbose and error-prone and no longer recommended.
classes with public mutable fields are not generally thread-safe.
Note that a nonzero-length array is always mutable, so it is wrong for a class to have a public static final array field, or an accessor that returns such a field.
An immutable class is simply a class whose instances cannot be modified. All of the information contained in each instance is fixed for the lifetime of the object, so no changes can ever be observed.
it is possible to return empty collections and arrays without allocating them.
return new ArrayList<>(cheesesInStock);
Collections.emptyList method. If you were returning a set, you’d use Collections.emptySet; if you were returning a map, you’d use Collections.emptyMap. But remember, this is an optimization, and it’s seldom called for.
primitives have only their values, whereas boxed primitives have identities distinct from their values.
primitive types have only fully functional values, whereas each boxed primitive type has one nonfunctional value, which is null,
primitives are more time- and space-efficient than boxed primitives.
To achieve acceptable performance, use a StringBuilder in place of a String to store the statement under construction:
conventions, many of which are contained in The Java Language