Chapter 4. Classes and Interfaces
Item 12: Minimize the accessibility of classes and members
The rule of thumb is that you should make each class or member as inaccessible as possible. With the exception of public static final fields, public classes should have no public fields. Ensure that objects referenced by public static final fields are immutable.
A protected member is part of the class’s exported API and must be supported forever. The need for protected members should be relatively rare.
If a method overrides a superclass method, it is not permitted to have a lower access level in the subclass than it does in the superclass.
It is nearly always wrong to have public static final array field.
Item 13: Favor immutability
Classes should be immutable unless there’s a very good reason to make them mutable. Immutable classes are easier to design, implement, and use than mutable classes. They are less prone to error and are more secure. Immutable objects are inherently thread-safe; they require no synchronization.
Not only can you share immutable objects, but you can share their internals. Immutable objects make great building blocks for other objects.
The only real disadvantage of immutable classes is that they require a separate object for each distinct value.
To make a class immutable:
- Don’t provide any methods that modify the object.
- Ensure that no methods may be overridden.
- Make all fields final.
- Make all fields private.
- Ensure exclusive access to any mutable components.
If a class cannot be made immutable, you should still limit its mutability as much as possible.
Item 14: Favor composition over inheritance
Unlike method invocation, inheritance breaks encapsulation. Inheritance is appropriate only when a genuine subtype relationship exists between the subclass and the superclass.Use composition and forwarding instead of inheritance, especially if an appropriate interface to implement a wrapper class exists. Wrapper classes are not suited for use in callback frameworks
Item 15: Design and document for inheritance or else prohibit it
The class must document precisely the effects of overriding any method. For effective inheritance, a class may have to provide hooks into its internal workings in the form of judiciously chosen protected methods or,in rare instances, protected fields.
Constructors must not invoke overridable methods, directly or indirectly. Neither clone nor readObject may invoke an overridable method, directly or indirectly. readResolve and writeReplace method should be protected instead of private if a Serializable class is designed for inheritance.
Two ways to prohibit subclasing – declare the class final or make all constructors private.
Item 16: Prefer interfaces to abstract classes
Existing classes can be easily retrofitted to implement a new interface.
Interfaces are ideal for defining mixins.A mixin is a type that a class can implement in addition to its “primary type” to declare that it provides some optional behavior.
Interfaces allow the construction of nonhierarchical type frameworks. Interfaces enable safe, powerful functionality enhancements via the wrapper class idiom (Item 14). You can combine the virtues of interfaces and abstract classes by providing an abstract skeletal implementation class to go with each nontrivial interface that you export.
It is far easier to evolve an abstract class than it is to evolve an interface.Design all of your public interfaces with the utmost care and test them thoroughly by writing multiple implementations
Item 17: Use interfaces only to define types
The constant interface pattern is a poor use of interfaces. To export constants, define them in the classes, or interface or use enumerated type or utility classes.
Item 18: Favor static member classes over nonstatic
There are four kinds of nested classes: static member classes, nonstatic member classes, anonymous classes, and local classes.All but the first kind are
known as inner classes.
One common use of a nonstatic member class is to define an Adapter [Gamma98, p.139] that allows an instance of the outer class to be viewed as an instance of some unrelated class.
If you declare a member class that does not require access to an enclosing instance,remember to put the static modifier in the declaration,
Assuming the class belongs inside a method, if you need to create instances from only one location and there is a preexisting type that characterizes the class, make it an anonymous class; otherwise, make it a local class.