[Effective Java 3rd Edition](https://www.amazon.co.jp/Effective-Java-%E7%AC%AC3%E7%89%88-%E3%], which is a must-have book for intermediate Java users and above. 82% B8% E3% 83% A7% E3% 82% B7% E3% 83% A5% E3% 82% A2% E3% 83% BB% E3% 83% 96% E3% 83% AD% E3% 83% 83% E3% 82% AF-ebook / dp / B07RHX1K53) has a Kindle version, so I will summarize it.
Previous: Effective Java 3rd Edition Chapter 3 Methods Common to All Objects Next: Effective Java 3rd Edition Chapter 5 Generics
--Each class or member should be as inaccessible as possible.
--There are public and package private, and it should be package private as much as possible. Because it is no longer a public API for packages. --If a top-level package private class or interface is used by only one class, consider making it a private nested class within that class.
--Everything should be private at first, and only when you need to access other classes in the same package. --For members of the public class, accessibility is greatly increased if the package is changed from private to protected. --The need for protected members should be relatively rare. --When overriding a method of a superclass, the access level that the method has in the superclass is not allowed to be narrowed in the subclass (Java specification). --To some extent it is permissible to relax access restrictions on classes, interfaces and members for ease of testing. From private to packaging private. No more is accepted. --Instance fields should not be public. When it's a non-final, variable object reference, it gives up limiting the values that can be stored in that field. As a result, classes with public variable fields are generally not thread-safe. --Use public static final to expose constants. It is customary to use capitalized, underscore-separated names. It is imperative to have either a basic data type or a reference to an immutable object. Because the value will change. Note that non-zero length arrays are always variable.
//Potential security hole (the contents of the array can be changed)
public static final Thing[] VALUES = { ... };
//Solution 1. Returns a public immutable list
private static final Thing[] PRIVATE_VALUES = { ... };
public static final List<Thing> VALUES =
Collections.unmodifiableList(Arrays.asList(PRIVATE_VALUES));
//Solution 2. Returns a copy of the array in the public method
private static final Thing[] PRIVATE_VALUES = { ... };
public static final Thing[] values() {
return PRIVATE_VALUES.clone();
}
--Public classes should not expose variable fields. It should have a private field and a public accessor method (getter), and a mutator (setter) for variable classes. --For package-private or private nested classes, exposing their data fields directly is essentially fine.
--Immutable objects are simple. In essence thread safe. --For immutable classes, it is not necessary to provide clone method or copy constructor, and it should not be provided. --To make a class immutable, follow the following five principles. --Does not provide a method to change the state of an object. --Don't extend the class. --Make all folds final. --Make all folds private. --Guarantee exclusive access to variable components. --The practical drawback of immutable objects is that they require separate objects for different individual values. --Classes should be immutable unless there is a good reason to make them variable. --If you can't make a class immutable, you should limit its variability as much as possible.
--Inheritance, when used improperly, creates fragile software. Inheritance breaks encapsulation. The proper functioning of subclasses depends on the implementation of the superclass. --Instead of extending an existing class, give the new class a private field that references an instance of the existing class. This design is called composition. --Each instance method of the new class calls the method corresponding to the existing instance of the class it holds and returns the result. This is called a transfer, and the new class of methods is called a transfer method. --The combination of composition and transfer is sometimes loosely referred to as delegation. Technically, it's not a delegation unless the wrapper object passes itself to the wrapped object.
--Designing a class for inheritance imposes considerable restrictions on that class. All self-use of the class must be documented, and once documented, it must be followed as long as the class exists.
--Use the Javadoc tag of @implSpec
to document for inheritance.
--The best solution is to ban subclasses of classes that are neither designed nor documented for safe subclassing. There are two ways to ban subclasses.
--Declare the class final.
--Make the class constructor private or package private and add a public static factory method as an alternative to the constructor.
--If there is an obvious implementation of a method with an interface, consider providing implementation assistance in the default method format. Providing default methods for Object methods such as equals and hashCode is not allowed. --The interface is not allowed to contain instance fields or non-public static members (other than private static methods). --By providing an abstract skeleton implementation class that accompanies an interface, you can combine the strengths of the interface and the abstract class. The skeleton implementation is based on the basic methods of the interface and implements the remaining non-basic methods of the interface. Most of the interface implementation is done by extending the skeletal implementation. (* Template Method * pattern) --By convention, the skeleton implementation class is named Abstract * Interface *. --For example, the collection framework provides skeletal implementations that accompany each major collection interface: AbstractCollection, AbstractSet, AbstractList, AbstractMap. --The great thing about skeleton implementation is that it provides implementation assistance, which is an abstract class, without imposing serious restrictions on the abstract class's role as a type definition. --A class that implements an interface can hold an instance of a private inner class that extends the skeleton implementation and forward the interface call to that instance. This technique is called pseudo-multiple inheritance.
--Before Java8, when you add a new method to an interface, the existing implementation doesn't have that method yet and you get a compile error. Java 8 added default method syntax, but adding methods to existing interfaces is risky. --The default method may be able to compile the interface implementation without errors or warnings, but it may fail at runtime. --Even if the default methods are part of the Java platform, careful interface design remains important. Adding methods carries a great deal of risk. --It is important to test a new interface before releasing it. At a minimum, three different implementations should be implemented and tested. It is difficult to fix interface defects after release.
--The interface, when implemented in a class, acts as a type that can be used to reference that instance. --You should not use the constant interface, which is just an interface for defining constants. --Constants should be provided in enum types or non-instantiable utility classes.
--A class that has two or more characteristics and switches between them with an enum is called a tagged class, and has many drawbacks. Hard to read, increased memory, verbose, apologetic and inefficient. --Subtype to define a single data type that can represent objects with multiple characteristics. --Define an abstract class that contains abstract methods for individual operations. If there is common behavior or data, put it in an abstract class. --Define a subclass that embodies the root class for each characteristic.
――Four kinds of nested classes --Static member class (inner class) --Non-static member class --Anonymous class --Local class --The only syntactic difference between static and non-static member classes is that static member classes have a static modifier in their declaration. These two types of nested classes are different. --Each instance of a non-static member class is implicitly associated with the enclosing instance of the class that contains it. Within an instance method of a non-static member class, you can call the method on the enclosing instance, or you can get a reference to the enclosing instance using the qualified this syntax. -(Planned to be added)
static member class
class Outer {
private int outerField;
private static int a;
//static member class
static class Inner {
void innerMethod() {
//Only available for static external class members
a = 10;
}
}
//Methods inside the outer class
void outerMethod() {
Inner ic = new Inner();
}
}
class Main {
public static void main(String[] args) {
// Outer.Used in Inner
Outer.Inner ic = new Outer.Inner();
ic.innerMethod();
}
}
Non-static member class
class Outer {
private static int outerField;
private int b;
//Non-static member class
class Inner {
void innerMethod() {
outerField = 10;
b = 5;
}
}
//Methods inside the outer class
void outerMethod() {
Inner ic = new Inner();
}
}
class Main {
public static void main(String[] args) {
Outer o = new Outer();
// o.Used in new
Outer.Inner in = o.new Inner();
}
}
--Do not put multiple top-level classes in a single source file. The reason is that the compiler may not recognize the class correctly.
Recommended Posts