Item 17: Minimize Mutability 83

Item 17: Minimize Mutability 83

80 CHAPTER4 CLASSESANDINTERFACES ITEM 17: MINIMIZE MIJTABILITY 81 Item mutability 17: Minimize // Innutable conplex number class public final class Complex { An immutable class is simply a class whose instances cannot be modified. A1l of private final double re; the information contained in each instance is fixed for the lifetime of the object, so private final double im; no changes can ever be observed. The Java platform libraries contain many public Complex(double re, double im) { immutable classes, including Stri ng, the boxed primitive classes, and this.re = re; Bigrnteger and BigDecimal. There are many good reasons this.im = im; for this: Immutable 1 J classes are easier to design, implement, and use than mutable classes. They are less prone to effor and are more secure. public double realParto { return re; } public double To make a class immutable, follow these five rules: imaginaryPartO { return im; } public Complex plus(Complex c) { 1. Donot provide methods that modify the object's state (known as mutators). return new Complex(re + c.re, im + c.im); ] 2. Ensure that the class can't be extended. This prevents careless or malicious public Complex minus(Complex c) subclasses from compromising the immutable behavior of the class by { return new Complex(re - c.re, im - c.im); behaving as if the object's state has changed. Preventing subclassing is ] generally accomplished by making the class final, but there is an alternative public Complex times(Complex c) that we'11 discuss later. { return new Complex(re :r c.Fê - im 't ç.jp, 3. Make all fÏelds fÏnal. Fê :! C,im + im rr c.fe); This clearly expresses your intent in a manner that is en- ] forced by the system. Also, it is necessary to ensure correct behavior if a refer- ence to a newly created instance is passed from one thread to another without public Complex dividedBy(Compiex c) { double tmp c.r€ :! c.re + c.im * c.im; synchronization, as spelled out in the memory model 17.5; Goetz06, 16]. = [JLS, return new Complex((re rr c.tê + im,', c.im) / tmp, 4. Make all fields private. This prevents clients from obtaining access to (im,'. c.re - re,,. c.im) / tmp); ] mutable objects referred to by fields and modifying these objects directly. While it is technically permissible for immutable classes to have public final @Override public boolean equals(Object o) { fields containing primitive if (o == this) values or references to immutable objects, it is not return true; recommended because it precludes changing the internal representation in a if (l (o instanceof Complex)) later release (Items 15 and 16). retu rn fal se; Compl ex c = (Compl ex) o; 5. Ensure exclusive access to any mutable components. If your class has any page fields that refer to mutable objects, ensure that clients of the class cannot obtain // See 47 to find out why we use compare instead of == retu rn Doubl e. compare (c . re re) == 6 references to these objects. Never initialize such a field to a , client-provided && Double.compare(c.im, im) == 6' object reference or return the field from an accessor. Make defensive copies ] (Item 50) in constructors, accessors, and readObject methods (Item 88). @Override public 'int hashCodeO { return 31''. Double.hashCode(re) + Double.hashCode(im) ; ] Many of the example classes in previous items are immutable. One such class is PhoneNumber in Item 11, which has accessors for each attribute but no cone- @Override public String tostrinSO { return "(" + re + " + " + im + "i)"; sponding mutators. Here is a slightly more complex example: ] ] 80 CHAPTER 4 CLASSES AND INTERFACES ITEM ]7: MINIMIZEMUTABILITY 8I Item mutability 17: Minimize // Tmnutable complex number class publ -i c f i nal cl ass Compl ex { An immutable class is simply a class whose instances cannot be modified. All of private final double re; the information contained in each instance is fixed for the lifetime of the object, so private final double im; no changes can ever be observed. The Java platform libraries contain many public Complex(double re, double im) { immutable classes, including Stri ng, the boxed primitive classes, and thi s. re = re; Bigrnteger and BigDecimal. There are many good reasons for this.im = im; this: Immutable ] classes are easier to design, implement, and use than mutable classes. They are less prone to error and are more secure. public double realPartO { return re; } public double To make a class immutable, follow these five rules: imaginaryPartO { return im; } public Complex plus(Complex c) { 1. Don't provide methods that modify the object's state (known as mutators). return new Complex(re + c. re, im + c.im); ] 2. Ensure that the class can't be extended. This prevents careless or malicious public Complex minus(Complex c) subclasses from compromising the immutable behavior of the class by { return new Complex(re - c.re, im - c.im); behaving as if the object's state has changed. Preventing subclassing is ] generally accomplished by making the class final, but there is an alternative public Complex times(Complex that we'll discuss later. c) { return new Complex(re :! c. F€ - im 't ç. jp, 3. Make all fields final. This Fê :t C,im + im ii c,fe); clearly expresses your intent in a manner that is en- ] forced by the system. Also, it is necessary to ensure correct behavior if a refer- ence to a newly created instance is passed from one thread to another without public Complex dividedBy(Complex c) { double tmp = c.l€ :! c.re + c.im c.im; synchronization, as spelled out in the tnemory model [JLS, 17.5; Goetz06, 16]. '', return new Complex((re :k C. rê + im ,,, c.im) / tmp, 4. Make all fïelds private. This prevents clients from obtaining (im,r c.re - re,'. c.im) / tmp); access to ] mutable objects referred to by fields and modifying these objects directly. While it is technically permissible for immutable classes to have public final @0verride public boolean equals(Object o) { fields containing primitive values if (o == this) or references to immutable objects, it is not return true; recommended because it precludes changing the internal representation in a if (! (o instanceof Complex)) later release (Items 15 and 16). return fal se; Compl ex 6 = (Compl ex) o; 5. Ensure exclusive access to any mutable components. If your class has any page fields that refer to mutable objects, ensure that clients of the class cannot obtain // See 47 to find out why we use compare instead of == return Doubl e. compare(c. re, re) == 6 references to these objects. Never initialize such a field to a client-provided -im) && Doubl e . compare (c . i m, == 6 ' object reference or return the field from an accessor. Make defensive copies ] (Item 50) in constructors, accessors, and readObject methods (Item 88). @Override public int hashCodeO { return 31''. Double.hashCode(re) + Double.hashCode(im) ; ] Many of the example classes in previous items are immutable. One such class is PhoneNumber in Item 11, which has accessors for each attribute but no corre- @Override public String toStrinSO { return "(" + re + " + " + im + "i)"; sponding mutators. Here is a slightly more complex example: ] ] 82 CHAPTER 4 CI"ASSES AND INTERFACES ITEM 17: MINIMIZE MUTABILITY 83 This class represents a complex number (a number with both real and imagi- costs. Opting for static factories in place of public constructors when designing a nary parts). In addition to the standard Object methods, it provides accessors for new class gives you the flexibility to add caching later, without modifying clients. the real and imaginary parts and provides the four basic arithmetic operations: A consequence of the fact that immutable objects can be shared freely is that addition, subtraction, multiplication, and division. Notice how the arithmetic oper- you never have to make defensive copies of them (Item 50). In fact, you never ations create and return a new Compl ex instance rather than modifying this have to make any copies at all because the copies would be forever equivalent to instance. This pattern is known as the functional approach because methods return the originals. Therefore, you need not and should not provide a cl one method or the result of applying a function to their operand, without modifying it. Contrast it copy constructor (Item 13) on an immutable class. This was not well understood to the procedural or imperative approach in which methods apply a procedure to in the early days of the Java platform, so the Stri ng class does have a copy con- their operand, causing its state to change. Note that the method names are preposi- structor, but it should rarely, if ever, be used (Item 6). tions (such as pl us) rather than verbs (such as add). This emphasizes the fact that Not only can you share immutable objects, but they can share their inter- methods don't change the values of the objects. The B'iglntege r and Bi gDec'ima'l nals. For example, the Biglnteger class uses a sign-magnitude representation classes did not obey this naming convention, and it led to many usage effors. internally. The sign is represented by an i nt, and the magnitude is represented by The functional approach may appear unnatural if you're not familiar with it, an i nt array. The negate method produces a new Bi glntege r of like magnitude but it enables immutability, which has many advantages. Immutable objects are and opposite sign. It does not need to copy the affay even though it is mutable; the simple. An immutable object can be in exactly one state, the state in which it was newly created Bi glnteger points to the same internal array as the original.

View Full Text

Details

  • File Type
    pdf
  • Upload Time
    -
  • Content Languages
    English
  • Upload User
    Anonymous/Not logged-in
  • File Pages
    7 Page
  • File Size
    -

Download

Channel Download Status
Express Download Enable

Copyright

We respect the copyrights and intellectual property rights of all users. All uploaded documents are either original works of the uploader or authorized works of the rightful owners.

  • Not to be reproduced or distributed without explicit permission.
  • Not used for commercial purposes outside of approved use cases.
  • Not used to infringe on the rights of the original creators.
  • If you believe any content infringes your copyright, please contact us immediately.

Support

For help with questions, suggestions, or problems, please contact us