Immutable classes, which are classes that an instance cannot be modified, and all information contained in an instance is fixed throughout the life cycle of the object.
Common examples are string, basic types of encapsulation classes, BigDecimal, BigInteger.
Relative and mutable classes, non-changeable and easy to design, implement, use, and more stable (less prone to error) more secure. For example, immutable classes are inherently thread-safe and do not require synchronous processing and are very handy to use.
We have 5 principles to design immutable classes
- No method is provided to modify the state of the object. (This approach also becomes mutator, the corresponding term " variability (mutability)")
- Ensure that the class is not extended (extends) to prevent the object state from being modified by subclasses. The way to prevent scaling is usually final.
- Try to make all field plus final.
- Try to make all field private. Although adding final to a base type or to an immutable reference field can prevent the field from being modified directly, we also need to consider changing the field representation in a later release.
- Ensure exclusive access to any mutable components.
That is, if a field points to a mutable object, you need to prevent the user from getting the Mutable object directly. You can solve this problem by returning copies of objects in the constructor, getter, ReadObject.
As an example of the code in the book, this is a typical immutable class:
Public final class Complex {private Final double re; private Final Double im; Public Complex (double Re, double im) {this.re = re; this.im = im; }//accessors with no corresponding mutators public double Realpart () {return re; } public double Imaginarypart () {return IM; } public Complex Add (Complex c) {return new Complex (re + c.re, im + c.im); } public Complex Subtract (Complex c) {return new Complex (Re-c.re, im-c.im); } public Complex Multiply (Complex c) {return new Complex (RE * C.re-im * c.im, RE * c.im + im * c.re); } public Complex divide (Complex c) {Double TMP = c.re * c.re + c.im * c.im; return new Complex ((RE * c.re + im * c.im)/tmp, (IM * c.re-re * c.im)/tmp); } @Override public boolean equals (Object o) {if (o = = this) return true; if (! ( o instanceof Complex)) return false; Complex C = (Complex) o; See page "Find out" why do we use compare instead of = = return Double.compare (Re, c.re) = = 0 && Double. Compare (IM, c.im) = = 0; } @Override public int hashcode () {int result = + hashdouble (re); result = * result + hashdouble (IM); return result; } private int hashdouble (double val) {Long longbits = double.doubletolongbits (re); return (int) (longbits ^ (longbits >>> 32)); } @Override Public String toString () {return "(" + Re + "+" + im + "i)"; }}
Since immutable objects are inherently thread-safe, immutable objects are free to pass, without even having to consider copying instances in the constructor or getter.
However, as in the preceding code, a separate object is returned when the immutable class method is used to change its own state.
If you create objects with a high overhead, this can cause performance problems.
In the position of the class provider, there are two ways we can solve this problem:
- Use the basic type as much as possible within the class.
- If you can pre-think that those states will often change, then provide a package-level private matching class, for example, StringBuilder is relative to string.
Also, if, for some reason, you cannot use the final modifier immutable class, but you do not want to be extended, there are other methods in addition to using final.
The method is to replace all public constructors with the public static factory method.
Like what:
public static Complex valueOf(double re, double im) { return new Complex(re, im);}public static Complex valueOfPolar(double r, double theta) { return new Complex(r * Math.cos(theta), r * Math.sin(theta));}
Effective Java-minimizing variability