The primary purpose of hiding information is to separate it from the system configuration so that it can be developed, tested, optimized, understood, and modified independently.
Class accessibility is only public or package-private (no access modifier).
If a package-private class is called by only one class, you should consider making it a private static nested class to make it less likely to be accessed.
From Java9, module system is adopted as an access control mechanism.
Point.java etc. in java.awt class has public accessibility of field variables, but it seems to do so due to performance problems.
If it is an immutable field variable, there is little harm even if it is public, but it is better to stop it.
Immutable classes are easier to design, use, and implement than variable classes.
When creating an immutable class, follow the 5 rules below.
Do not provide methods that change the state of objects
Make it impossible to inherit
Make all fields final
Make all fields private
Prevent access to variable classes
Immutable classes are thread-safe in nature and do not require synchronization.
The disadvantage of immutable classes is that they create separate objects for different values, which is costly. The solution to this is the companion class. A specific example is a variable class StringBuilder corresponding to the immutable class String.
As a method of not inheriting the immutable class, there is a method of creating a factory method public with the constructor as private as a method other than adding the final modifier to the class.
When BigInteger and BigDecimal were implemented, it was not known that immutable classes should not be inherited, so inheritance is possible.
As a general rule, the field should be private final to get as close to the immutable class as possible. (CountDownLatch is a good example)
It is dangerous to inherit a concrete class across packages. There are two possible problems:
Superclass implementations can change from release to release. Subclasses may have to make changes accordingly.
It seems that it may become a security hole when a new method is added to the superclass. (** It doesn't come at all **)
To avoid inheritance, it can be realized by importing the class that was originally supposed to be a superclass as a private final field (composition) and referencing the method of the imported field in each method (forwarding).
The drawback of making ↑ is that it is not suitable for callback framework. Wrapped objects don't know which ones are wrapped, so they can't make subclass calls with a reference to themselves.
B extends A should be avoided unless the relationship B is a A really holds. This is not protected by the Java platform library, and Stack is not a Vector, so Stack should not inherit from Vector, and so is the relationship between Properties and HashList.
For overridable methods, you need to write your own usage. The Javadoc annotation for that is @implSpec.
Generally, a good API describes what to do and not how to do it, but it does because detailed specifications are required for safe inheritance.
The only way to test the design of the inherited class is to actually create a subclass and test it. If you're aiming for a widely used library, once you release a protected method, it's almost immutable, so be sure to create a subclass before releasing it.
Do not call methods that can be aurarided in the constructor. Because, before the processing of the constructor of the subclass is executed, the processing of the constructor of the superclass is always executed, but "There is processing such as field initialization of the subclass in the constructor of the subclass, and the overridden method used that field. In the case of "performing processing", to show non-intuitive behavior.
Basically, Serializable and Clonable should not be implemented in the class designed as the inheritance source, but in case of unavoidable circumstances, the methods that can be overridden in the readObject method and clone method Don't call. If you call it, you may try to make changes to the clone object even though it has not been created.
It's easy to modify an existing class to implement a newly born interface.
The interface is great for defining mixins.
What is a mixin? Code that is not intended to operate independently (code that you want to reuse) is defined in advance, and if necessary, it is mixed into the class (implements in Java) to reuse the process. It is a mechanism to encourage.
https://ja.wikipedia.org/wiki/Mixin
http://equj65.net/tech/java8mixin/
What is a non-primitive interface method?
There is a skeletal implementation class that hides the advantages of interface and the advantages of abstract classes. The skeleton implementation class is called AbstractInterface, and the AbstractCollection and AbstractSet of CollectionsFW correspond to it. (Originally these should be called SkeletalCollection, SkeletalSet, but it is customarily called this)
The skeleton implementation class is created to override some of the methods provided by the implemented interface and leave the rest of the methods to override in a class that inherits from the skeleton implementation class. Without this skeleton implementation class, the implementer would have to implement the interface directly and override all the methods provided, but sandwiching the skeleton implementation class reduces the methods that the implementer should override (wrong). The risk of overriding is also reduced). ** Is it OK to understand that this is an advantage? ** **
There is a risk in adding methods to existing interfaces.
As an example, removeIf was added to the Collection as the default method, but when you call this removeIf on the SynchronizedCollection of the Apache Commons library that implements the Collection, it is called as an out-of-sync method, breaking the convention for using SynchronizedCollection. Will be done. The Java library overrides the removeIf method in Collections.synchronizedCollection to prevent this from happening.
You should not create a constant interface that only defines constants. It's done by java.io.ObjectStreamConstants but shouldn't be imitated. The reason below.
You must continue to implements to maintain binary compatibility, even when you no longer need the constants. (** Binary compatibility ?? **)
Implements a constant interface pollutes the namespace.
Another rational way to define constants is:
If the value you define is closely tied to an existing class, add it there.
Constant Use Enum if the value to be defined is the best to enumerate.
Otherwise, use the utility class.
// Constant utility class
public interface PhysicalConstants {
static final double AVOGADROS_NUMBER = 6.02214199e23;
static final double BOLTZMANN_CONSTANT = 1.3806503e-23;
static final double ELECTRON_MASS = 9.10938188e-31;
}
// Use of static import to avoid qualifying constants
import static com.effectivejava.science.PhysicalConstants.*;
public class Test {
double atoms(double mols) {
return AVOGADROS_NUMBER * mols;
}
...
// Many more uses of PhysicalConstants justify static import
Recommended Posts