Effective Java
Rate it:
Open Preview
Read between March 23 - August 10, 2018
5%
Flag icon
This client code is easy to write and, more importantly, easy to read. The Builder pattern simulates named optional parameters as found in Python and Scala.
6%
Flag icon
In summary, the Builder pattern is a good choice when designing classes whose constructors or static factories would have more than a handful of parameters, especially if many of the parameters are optional or of identical type.
9%
Flag icon
Normally, an uncaught exception will terminate the thread and print a stack trace, but not if it occurs in a finalizer—it won’t even print a warning. Cleaners do not have this problem because a library using a cleaner has control over its thread.
9%
Flag icon
Throwing an exception from a constructor should be sufficient to prevent an object from coming into existence; in the presence of finalizers, it is not.
12%
Flag icon
It turns out that this is a fundamental problem of equivalence relations in object-oriented languages.
12%
Flag icon
There is no way to extend an instantiable class and add a value component while preserving the equals contract, unless you’re willing to forgo the benefits of object-oriented abstraction.
16%
Flag icon
The Cloneable interface was intended as a mixin interface (Item 20) for classes to advertise that they permit cloning. Unfortunately, it fails to serve this purpose. Its primary flaw is that it lacks a clone method, and Object’s clone method is protected.
16%
Flag icon
Though the specification doesn’t say it, in practice, a class implementing Cloneable is expected to provide a properly functioning public clone method. In order to achieve this, the class and all of its superclasses must obey a complex, unenforceable, thinly documented protocol. The resulting mechanism is fragile, dangerous, and extralinguistic: it creates objects without calling a constructor.
17%
Flag icon
This is a fundamental problem: like serialization, the Cloneable architecture is incompatible with normal use of final fields referring to mutable objects, except in cases where the mutable objects may be safely shared between an object and its clone. In order to make a class cloneable, it may be necessary to remove final modifiers from some fields.
18%
Flag icon
Object’s clone method is not synchronized, so even if its implementation is otherwise satisfactory, you may have to write a synchronized clone method that returns super.clone().
18%
Flag icon
A better approach to object copying is to provide a copy constructor or copy factory.
18%
Flag icon
Virtually all of the value classes in the Java platform libraries, as well as all enum types (Item 34), implement Comparable.
21%
Flag icon
It is too early to say whether modules will achieve widespread use outside of the JDK itself. In the meantime, it seems best to avoid them unless you have a compelling need.
23%
Flag icon
Inheriting from ordinary concrete classes across package boundaries, however, is dangerous. As a reminder, this book uses the word “inheritance” to mean implementation inheritance (when one class extends another). The problems discussed in this item do not apply to interface inheritance (when a class implements an interface or when one interface extends another).
24%
Flag icon
This is an unfortunate consequence of the fact that inheritance violates encapsulation. To document a class so that it can be safely subclassed, you must describe implementation details that should otherwise be left unspecified.
25%
Flag icon
Constructors must not invoke overridable methods, directly or indirectly.
25%
Flag icon
Note that it is safe to invoke private methods, final methods, and static methods, none of which are overridable, from a constructor.
25%
Flag icon
it should be apparent that designing a class for inheritance requires great effort and places substantial limitations on the class.
26%
Flag icon
Interfaces are ideal for defining mixins. Loosely speaking, a mixin is a type that a class can implement in addition to its “primary type,” to declare that it provides some optional behavior.
27%
Flag icon
interfaces should be used only to define types. They should not be used merely to export constants.
30%
Flag icon
you can’t put any element (other than null) into a Collection<?>.
32%
Flag icon
Because of erasure, the only parameterized types that are reifiable are unbounded wildcard types such as List<?> and Map<?,?> (Item 26). It is legal, though rarely useful, to create arrays of unbounded wildcard types.
35%
Flag icon
Do not use bounded wildcard types as return types. Rather than providing additional flexibility for your users, it would force them to use wildcard types in client code.
36%
Flag icon
Heap pollution occurs when a variable of a parameterized type refers to an object that is not of that type [JLS, 4.12.2]. It can cause the compiler’s automatically generated casts to fail, violating the fundamental guarantee of the generic type system.
36%
Flag icon
// Mixing generics and varargs can violate type safety! static void dangerous(List<String>... stringLists) {     List<Integer> intList = List.of(42);     Object[] objects = stringLists;     objects[0] = intList;             // Heap pollution     String s = stringLists[0].get(0); // ClassCastException }
Daniel Berg
What a shit show!
37%
Flag icon
the varargs parameter array is used only to transmit a variable number of arguments from the caller to the method—which is, after all, the purpose of varargs—then the method is safe.
38%
Flag icon
When a class literal is passed among methods to communicate both compile-time and runtime type information, it is called a type token [Bracha04].
38%
Flag icon
In fact, Java’s type system is not powerful enough to express this. But we know that it’s true, and we take advantage of it when the time comes to retrieve a favorite.
Daniel Berg
HLists.
38%
Flag icon
If you try to store your favorite List<String>, your program won’t compile. The reason is that you can’t get a Class object for List<String>. The class literal List<String>.class is a syntax error, and it’s a good thing, too. List<String> and List<Integer> share a single Class object, which is List.class. It would wreak havoc with the internals of a Favorites object if the “type literals” List<String>.class and List<Integer>.class were legal and returned the same object reference. There is no entirely satisfactory workaround for this limitation.
53%
Flag icon
Collection or an appropriate subtype is generally the best return type for a public, sequence-returning method.
54%
Flag icon
parallelizing a pipeline is unlikely to increase its performance if the source is from Stream.iterate, or the intermediate operation limit is used.
57%
Flag icon
selection among overloaded methods is static, while selection among overridden methods is dynamic.
70%
Flag icon
Given the almost universal acceptance of this convention, it’s best not to implement any new Error subclasses. Therefore, all of the unchecked throwables you implement should subclass RuntimeException (directly or indirectly). Not only shouldn’t you define Error subclasses, but with the exception of AssertionError, you shouldn’t throw them either.
76%
Flag icon
In summary, to avoid deadlock and data corruption, never call an alien method from within a synchronized region. More generally, keep the amount of work that you do from within synchronized regions to a minimum.
77%
Flag icon
Concurrent collections make synchronized collections largely obsolete. For example, use ConcurrentHashMap in preference to Collections.synchronizedMap. Simply replacing synchronized maps with concurrent maps can dramatically increase the performance of concurrent applications.