Effective Java




Effective Java
Programming Language Guide
Joshua Bloch
Addison-Wesley 2001, 252 pages

1-INTRODUCTION

2-CREATING AND DESTROYING OBJECTS
   
Item 1. Consider providing static factory methods instance of constructors p5
Item 2. Enforce the singleton property with a private constructor p10
Item 3. Enforce noninstantiability with a private constructor p12
Item 4. Avoid creating duplicate objects p13
Item 5. Eliminate obsolete object references p17
Item 6. Avoid finalizers p20

3-METHODS COMMON TO ALL OBJECTS

Item 7. Obey the general contract when overriding equals p25
Item 8. Always override hashcode() when you override equals() p36
Item 9. Always override toString() p42
Item 10. Override clone() judiciously p45
Item 11. Consider implementing Comparable p53

4-CLASSES AND INTERFACES

Item 12. Minimize the accessibility of classes and members p59
Item 13. Favor immutability p63
Item 14. Favor composition over inheritance p71
Item 15. Design and document for inheritance or else probibit it p78
Item 16. Prefer interfaces to abstract classes p84
Item 17. Use interfaces only to define types p89
Item 18. Favor static member classes over nonstatic p91


5-SUBSTITUTES FOR C CONSTRUCTS

Item 19. Replace structures with classes p97
Item 20. Replace unions with classes hierarchies p100
Item 21. Replace enum constructs with classes p104
Item 22. Replace function pointers with classes and interfaces p115


6-METHODS

Item 23. Check parameters for validity p119
Item 24. Make defensive copies when needed p122
Item 25. Design method signatures carefully p126
Item 26. Use overloading judiciously p128
Item 27. Return zero-length arrays, not null p134
Item 28. Write doc comments for all exposed API elements p136

7-GENERAL PROGRAMMING

Item 29. Minimize the scope of local variables p141
Item 30. Know and use the libraries p145
Item 31. Avoid float and double if exact answers are required p149
Item 32. Avoid strings where other types are more appropriate p152
Item 33. Beware the performance of string concatenation p155
Item 34. Refer to objects by their interfaces p156
Item 35. Prefer interfaces to reflection p158
Item 36. Use native methods judiciously p161
Item 37. Optimize judiciously p162
Item 38. Adhere to generally accepted naming conventions p165

8-EXCEPTIONS

Item 39. Use exceptions only for exceptional conditions p169
Item 40. Use checked exceptions for recoverable conditions and
         run-time exceptions for programming errors p172
Item 41. Avoid unnecessary use of checked exceptions p174
Item 42. Favor the use of standard exceptions p176
Item 43. Throw exceptions appropriate to the abstraction p178
Item 44. Document all exceptions thrown by each method p181
Item 45. Include failure-capture information in detail messages p183
Item 46. Strive for failure atomicity p185
Item 47. Don't ignore excpetions p187
 
 
9-THREADS

Item 48. Synchronize access to shared mutable data p189
Item 49. Avoid excessive synchronization p196
Item 50. Never invoke wait() outside a loop p201
Item 51. Don't depend on the thread scheduler p204
Item 52. Document thead safety p208
Item 53. Avoid thread groups p211


10-SERIALIZATION

Item 54. Implement Serializable judiciously p213
Item 55. Consider using a custom serialized form p218
Item 56. Write readObject() methods defensively p224
Item 57. Provide a readResolve() method when necessary p230




1-INTRODUCTION

2-CREATING AND DESTROYING OBJECTS
   
Item 1. Consider providing static factory methods instance of constructors

  Advantages of factory methods over constructors
  a) Factory methods have names, unlike constructors
  b) Factory methods do not require to create a new object each time they're invoked
  c) Factory methods can return an object of any subtype of their return type

  Disadvantages of factory methods over constructors
  a) Classes w/o public or protected constructors cannot be subclassed
  b) Factory methods are not readily distinguishable from other static methods

Item 2. Enforce the singleton property with a private constructor

  public FileSystem {
    private static FileSystem instance = null;
    private FileSystem() {}
   
    public synchronized  FileSystem getInstance() {
      if (instance == null) {
        instance = new FileSystem();
      }

      return instance;
    }
  }

  a) instance created only when needed
  b) leave us the choice of changing the implementation later
     (e.g. return one instance per thread, one serialized instance,
           return null if a condition is not met etc.)

Item 3. Enforce noninstantiability with a private constructor

  //A utility class, to group related static methods 
  public (static) class Math {

    private Math() {}
   
    public static double sin(double theta) {..
    public static double cos(double theta) {..
    //
  }


  Attempting to enforce noninstantiatiability by making a class abstract
does not work: 1) this class can be subclassed, and subclass can be
instantiable; 2) it misleads the client into thinking the class was
designded for inheritance.
 
Item 4. Avoid creating duplicate objects

  //DON'T DO THIS
  public class Person {
    private final Date birthDate;

    public boolean isBabyBoomer() {
      Calendar c = Calendar.getInstance(TimeZone.getTimeZone("GMT"));
      c.set(1946, Calendar.JANUARY, 1, 0, 0, 0);
      Date boomStart = c.getTime();
      c.set(1965, Calendar.JANUARY, 1, 0, 0, 0);
      Date endStart = c.getTime();
      boolean after1945 = birthDate.compareTo(boomStart) >= 0;
      boolean before1965 = birthDate.compareTo(boomEnd) < 0;
      boolean babyBoomer = after1945 && before1965;
      return babyboomer;
    }
  }

  //BETTER
  public class Person {
    private final Date birthDate;
    private static final Date BOOM_START;
    private static final Date BOOM_END;

    static {
      Calendar c = Calendar.getInstance(TimeZone.getTimeZone("GMT"));
      c.set(1946, Calendar.JANUARY, 1, 0, 0, 0);
      BOOM_START = c.getTime();
      c.set(1965, Calendar.JANUARY, 1, 0, 0, 0);
      BOOM_END   = c.getTime();
    }

    public boolean isBabyBoomer() {
      boolean after1945 = birthDate.compareTo(BOOM_START) >= 0;
      boolean before1965 = birthDate.compareTo(BOOM_END) < 0;
      boolean babyBoomer = after1945 && before1965;
      return babyboomer;
    }
  }
 
Item 5. Eliminate obsolete object references

  Memory leaks also exist in garbage-collected languages, such as Java.
 
Item 6. Avoid finalizers

  a) You don't have control on finalizers invocation
  b) Provide explicit termination methods, such as Writer.close()


3-METHODS COMMON TO ALL OBJECTS

Item 7. Obey the general contract when overriding equals

  equals() methods are:
  a) reflexive, ie for all x, x.equals(x) must be true
  b) symmetric, ie for all x,y, if x.equals(y), then y.equals(x) 
  c) transitive, ie for all z,y,z, if x.equals(y) and y.equals(z), then x.equals(z)
  d) consistent, ie for all x.y, x.equals(y) return the same at each invocation
  e) not-nullity, ie for all not-null x, x.equals(null) must be false

Item 8. Always override hashcode() when you override equals()

  hashCode() methods are:
  a) consistent, ie for all x, x.hashCode() return the same integer at each invocation
  b) equivalent, for all x,y, if x.equals(y) == true, then x.hashCode() == y.hashCode()
  c) not-identity, for all x,y, f x.equals(y) == false,
     then x.hashCode(), y.hashCode() are not required to produce distinct integer codes
  d) fast to execute (faster than equals())

Item 9. Always override toString()

  For a class PhoneNumber, "418 682-999" is more intuitive than "PhoneNumber@165b9f"

  "Providing a god toString() implementation makes your class much more pleasant to use"
 
  toString():
    a) automatically invoked when instance passed to println, the string concatanator (+), or assert()
    b) [Marco]toString() result is diplayed in the debugger
 

Item 10. Override clone() judiciously


  For all x,
  a) x.clone() != z
  b) x.close().getClass() == x.getClass()
  c) x.clone().equals(x) should be true [strongly recommended]
 
Item 11. Consider implementing Comparable


  compareTo() methods are:
  a) symetric, i.e for all x,y, x.compareTo(y) = - y.compareTo(x)
  b) transitive, i.e for all x,y,z, if x.compareTo(y) > 0 and y.compareTo(z) > 0, then x.compareTo(z) > 0
  c) equivalence, i.e for all x,y,z, if x.compareTo(y) == 0, then sgn(x.compareTo(z)) == sgn(y.compareTo(z))
  d) equality, i.e. for all x,y, (x.compareTo(y) == 0) == (x.equals(y)) [strongly recommended, not mandatory]


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
  (to minimize coupling)

 
Item 13. Favor immutability

  C is immutable class if:
  a) C does not have any mutator (methods to modify the C's state)
  b) all methods of C are final (or C is final)
  c) all fields of C are final
  d) all fields of C are private
  e) exclusive access to any mutable components

  Advantages:
  a) Immutable objects are simple
  b) Immutable objetcs are inherently thread-sade; they require no synchronisation
  c) Immutable objetcts are shared freely
  d) Not only can you share immutable objects, but you can share their internals
  e) Immutable objects make great building blocks for other objects
 
  Disavantages:
  a) the only real disavantage is that immutable objetcs require a separate object for each distinct value


Item 14. Favor composition over inheritance

  Advantages:
    Safe to use within a package, implemented by the same programmers
    Safe to use when stable and clearly documented for extension (as an API)

  Desavantages:
    Unlike method invocation, inheritance breaks encapsulation [Snyder86]: subclasses
  depend on implementation details ot its superclass for its own function.

Item 15. Design and document for inheritance or else probibit it

  1) The class must document precisely the effects of overriding any method
  2) A class may have to provide hooks into its internal workings in the form of
     judiciously chosen protected methods (or in rare cases, protected fields).
  3) Constructors must not invoke overirrable methods, directly or indirectly
  4) Neither clone() nor readObject() may invoke an overridable methods, directly or indirectly.
  5) If your class si Serializable, readResolve() and writeReplace() must be protected rather than private
 
 Prohibit inheritance on class C by:
  a) Making C final;
  b) Making C's constructors private or package-private.
 
Item 16. Prefer interfaces to abstract classes

  Advantages:
  1) Existing classes can be retrofitted to implement a new interface.
  2) Interfaces are ideal for defining mixins. A mixin is a type that a class can implement
    in addittion of its "primary type" to declare some optional behavior. For instance,
    Comparable is a mixin interface that allow a class to declare that its instances
    are ordered w/ respect to other mutually comparable objects.
  3) Interfaces allow the construction of nonhierarchical type frameworks
  4) Interfaces allow safe, poerful functionnalities enhancements
  5) You can combine the virtues of interfaces and abstract classes by providing an
     abstract 'skeleton implementation' class to go w/ each nontrivial interface that
     you export.  E.g. in the Collections framework, Set and List interfaces have
     AbstractSet and AbstractList implementations.
 
Item 17. Use interfaces only to define types

  The constant interface pattern is a poor use of interfaces.

  //WRONG API
  public interface PhysicalConstants {
    public static final double AVOGADRO_NUMBER = 6.02e23;
    ...                        ELECTRON_MASS = 9.1e-31;
    ...
  }

  //WRONG USE
  import *.PhysicalConstants;

  public class ClientClass {
    public void method() {
      double x = AVOGADRO_NUMBER;
    }
  }

  HOW TO AVOID IT?

  1) Put constants in related classes.

  e.g. Integer and Float MIN_VALUE, MAX_VALUE

  2) Use enumerations

  3) Use utility classes (force client to qualified constants)
 
  public class PhysicalConstants {
    private PhysicalConstants() {}
    public static final double AVOGADRO_NUMBER = 6.02e23;
    ...                        ELECTRON_MASS = 9.1e-31;
    ...
  }

  eg. Math.PI;
 


Item 18. Favor static member classes over nonstatic

  class X {
    static class Y1 {}
    class class Y2 {}
  }

  Y1 is preferable than Y2 (because Y1 doesn't have acess to X's fields, so Y2 is more isolated)

  One common use of a nonstatic membre class is to define an Adapter [Gamma95, p139]
 
  e.g.
  public class MySet extends AbstractSet {

    public Iterator iterator() {
      return new MyIterator();
    }

    private class myIterator implements Iterator {
    }
  }


5-SUBSTITUTES FOR C CONSTRUCTS

Item 19. Replace structures with classes

   //WRONG: A STRUCT-LIKE CLASS
   public class Point1 {
     public float x;
     public float y;
   }

   //GOOD:
   public class Point2 {

     public float getX() {..}
     public float getY() {..}
     public void setX(float value) {..}
     public void setY(float value) {..}
   }

   Point2 is more maintainable thant Point2
   Point2's performance is equivalent to Point1  
 
Item 20. Replace unions with classes hierarchies

   abstract class Shape {
     abstract double area();
   }

   class Circle extends Shape {
     ..
   }

   class Rectangle extends Shape {
     ..
   }


   The designers of Java language chose to omit union construct because there
   is a much better mechanism for defining a single data type capable of
   representing objects of various types: subtyping.

Item 21. Replace enum constructs with classes

  [NOte: in Java 1.5 and +], enum is supported

Item 22. Replace function pointers with classes and interfaces

  The Comparator interface in Java is an exemple of Strategty pattern
 
  interface Comparator {
    int compareTo(Object that) {..}
  }

 

6-METHODS

Item 23. Check parameters for validity

  Typically the exception thrown will be IllegalArumentException, IndexOutOfBoundsException,
    NullPointerException or ArithmeticException.

  public BigInteger mod(BigInteger m) {
    if (m.signum <= 0) {
      throw new ArithmeticException() {}
    }
  }

  It is particularly important to check validity of parameters that are not used
  by a method but stored away for later use.

  When do not validate?
    In the case in which the validation would be expensive AND the validation is
    involve in a computation, a loop, etc.

    E.g. Collections.sort(List)
 
Item 24. Make defensive copies when needed

  You must program defensively with the assumption that clients of your class will do
  their best effort to destroy its invariants.  This may actually be true if someone
  tries to break the security of your system, but more likely your class will have to
  cope w/ unexpected behavior resulting from honest mistakes on the part of the
  programmers using your API.

  //Broken "immutable" time period class
  public final class Period {
    private final Date start;
    private final Date end;

    public Period(Date start, Date end) {
      if (start after end)
        throw new IllegalArgumentException(..)
   
      ..
    }
  }


Item 25. Design method signatures carefully

  a) Choose method names carefully

     read/write
     add/remove
     ect.

     be consistant (do not mix remove() and delete() in the same API for the same purpose)

  b) Dont't go overboard in providing convenience methods

     (provide 10-15 public methods per classes)

  c) Avoid long parameters lists

     three parameters at most

     long sequences of identically typed parameters are especially harmful.
     e.g method(true, true, false, true)

  d) for parameter types, favor interfaces over classes
    
     method(List l) is prefered to method(ArrayList l)

  e) use functions objects judiciously

     some legitime uses, such as anoymous class (if class is short)

     compare(list, new Comparator() {
       //anomymous class
     }

    
Item 26. Use overloading judiciously

   A safe policity is never to export overloadings w/ the same arity (nb of params)

   methods:
   for instance, the ObjectOutputStream class has writeBoolean(), writeInt() writeLong()
   i/o of overloading write() w/ different parameter type.

   write(null); //which overloading method is called?

   constructors: more difficult, because you cannot use a different name; use static
   factory method as an alternative.

   overloading w/ the same arity acceptable if types are unlinkely to be confused

   eg: new ArrayList(int) and new ArrayList(collection).
   (the client is unlikely to mix up int and collection)


Item 27. Return zero-length arrays, not null

   Product[] getProductsInStock() {

      Product[] products = null;          //wrong
      Product[] products = new Product[]; //good

      return products;
   }

   a) the client should not have to check for nullity

      if (products.size > 0) { //throws a NullPointerException?

   b) the argument of using null for performance purposes is wrong because:
      i) it is inadvisable to worry about performance at this level unless profiling has
          shown that the method causes a bottleneck (Item, 37)
      ii) the same empty array is returned at each invocation because zero-length arrays
          are immutable, and immutable objects may be shared freely (Item 13)


Item 28. Write doc comments for all exposed API elements

  a) To document your API properly, you must precede every exported class, interface,
     methods, constructors, fields with a doc comment

   b) The doc comment for a method should describe succintly the contract between
     the method and its client.



7-GENERAL PROGRAMMING

Item 29. Minimize the scope of local variables

   The C programming  language mandates that local variables must be declared
at the head of a block.  In Java, it is legal (and preferable) to declare variables
just before they are used.

   The most powelful technique to miniming the scope of a local variable is
to declare it where it is first used.

   a) The programmer can forget the variable's type/initial value if it is
      declared too early.
   b) If the programs evolves, it is easier to forget to remove an unused
      variable, or to overwrite an existing variable, if the varaible is declared
      too early.
   c) Nearly every local variable should be initialized; if you don't yet have
      the enough info to initialize it, postpone its declaration.


   Prefer:
   for (Iterator i = c.iterator(); i.hasNext(); ) {
     i.next();
   }
   //i inacessible

   //compile-time error is i used i/o i2
   for (Iterator i2 = c2.iterator(); i2.hasNext(); ) {
     i2.next();
   }

   to:
   Instead of:
   Iterator i = c.iterator();
   while (i.hasNext()) {
     i.next();
   }
   //i still acessible

   Iterator i2 = c2.iterator();
   while (i.hasNext()) {         //BUG i used i/o i2
     i2.next();
   }

   //High-performance idiom for loops
   for (int i=0, n=lise.size(); i<n; i++ ) {
     list.get(i);
   }

   //High-performance idiom (generalization)
   for (int i=0, n=lise.expensiveComputation(); i<n; i++ ) {
     list.get(i);
   }
 

Item 30. Know and use the libraries

   a) By using a std library, you take advantage of the knowledge of experts who wrote it,
      and the experience of those who used it.

   b) Std libraries tend to improve over time, with no effort on your part. i.e java.math
      in version 1.3 resulted in dramatic performance improvements.

   c) Std libraries tend to gain functionalities over time.

   d) If your code uses std library, is is more easily readable, maintainable, reusabled.

 
Item 31. Avoid float and double if exact answers are required

   Float and double types are designed for scientific and engineering calculations.

   Float and double types are particularly ill-suited for monetary calculations
because it's impossible to represent 0.1 (of any other negative power of 10) as
a float or double exactly.

   float credit = 1.03;     // $1.03 in your pocket
   float price  = 0.42;

   credit -= price;         // credit == 0.6100000001, not an isolated case

   float credit = 1.03;     // $1.03 in your pocket
   float unitPrice = 0.10   // 10 cents per unit
   int qty = 9;             // want to buy 9 units

   credit -= qty*unitPrice; // 0.099999999995

   You may think the problem could be solved merely by rounding results, but this doesn't always work.

   Problem: you have $1 in your pocket and you want to know how many candy you can afford.
   the 1st candy costs 10¢, the 2n 20¢, the 3rd 30¢, and so on.

   // Broken - uses float for monetary calculations
   public static void main(String[] args) {
     double funds = 1.00;
     int itemsBought = 0;

     for (double price = .10; funds < price; price += .10) {
        funds -= price;
        itemsBought++;
     }
     System.out.println(itemBought +" items bought");
     System.out.println("Change: "+funds);
   }

   //Result: 3 items bought, Change: 0.399999  -> WRONG !
  

Item 32. Avoid strings where other types are more appropriate

   a) String values are not validated

   Use boolean to store booleans (i/o "yes" or "no", what about "true" ?)
   Use float to store numeric (i/o "3.1416".. what about "3,1416", "030" )
   Use URL for urls..

   Note: for civic address, use String (not computation on civic adressees,
     and adresses may have special syntax: "50B", "10 1/2" )
  
   b) String are poor substitute for aggregate type
  
   String compoundKey = "class#instance";

 
Item 33. Beware the performance of string concatenation

   //Concatenate n strings requires time quadratic in n
   //Performs horribly
   public String concatenate() {
     String s = "";
     for (int i=0; i<nb; i++) {
       s += list.get(i);
     }

     return s;
   }

   Concatenate n strings requires time quadratic in n, because strings
   are immutable objects; when 2 strings are concatenated, the contents
   of both are copied.

   //better
   public String concatenate() {
     StringBuffer s = new StringBuffer(initialLength);
     for (int i=0; i<nb; i++) {
       s.append(list.get(i));
     }
93
     return s.tostring();
   }

   //tests w/ 100 elements show method2 is 90x faster


Item 34. Refer to objects by their interfaces

   ArrayList list = new ArrayList(); //bad
   List list = new ArrayList();      //good

   Advantages:
   a) your program is more flexible, e.g. you can change
  
   List list = new Vector();

   w/o changing the rest of the application

   It is entirely appropriate to refer to an object by a class
if no appropriate interface exists.

   String s = "";        //good, if we plan to use String's methods
   Serializable s = "";

Item 35. Prefer interfaces to reflection

   a) You lose all the benefits of compile-time type checking
   b) The code required to perform reflectivive access is clumsy and verbose
   c) Performance suffers

Item 36. Use native methods judiciously

   As of release 1.3, it is rarely advisable to use native methods for improved
performance.

 
Item 37. Optimize judiciously

   "More computing sins are committed in the name of efficiency (w/o necessarly
archieving it) than any other single reason" -William A Wulf 1972

   "We should forget about small efficienties, say 97% of the time: premature
optimization is the root of all evil".  Donald E Knuth, 1974

   "We follow two rules in the matter of optimization:
    Rule 1. Don't do it
    Rule 2 (for expert only) Don't do ityet-that is, not until you have a
      perfectly clear and unoptimized solution"  M. A Jackson, 1975

  a) Strive to write good programs rather than fast ones
 
  b) Strive to avoid design decisions that limit performance
 
  c) Consider the performance consequences of your API design decisions

  d) Measure performance before and after each attempted optimization
 

Item 38. Adhere to generally accepted naming conventions

   Sun Typographical conventions:
     package
     Class, Interface
     method
     variable
     CONSTANT

   Grammatical conventions:
     for class, use noun or noun phrase  (Writer)
     for interface, use noun (Comparator) or -ble adjective (Runnable, Accessible)
     for method, use verb or verb phrase : append(), drawImage()
     for boolean method, use 'is': isEmpty(), isEnabled(), etc.
     for accessor method, use getProperty() and setProperty()
     for conversion method, use toTarget(): toString(), toArray()

   Grammatical conventions for private variables are less important.
   Grammatical conventions for local variables are even less important.
    
 
8-EXCEPTIONS

Item 39. Use exceptions only for exceptional conditions

  //horrible use of exceptions
  try {
    int i=0;
   
    while(true) {
      a[i++] = 0;
    }
  } catch (ArrayIndexOutOfBoundsException ex) {
  }


  //better
  for (int i=0; i<nb; i++) {
    a[i++] = 0;
  }


  a) Because exceptions are designed for use under exceptional circumstances, few
     JVM implementations attemp to optimize their performance.  It is generally
     expensive to create, throw and catch exceptions.

  b) Placing code inside a try-catch block precludes certain optimizations
     that modern JVM implementations might otherwise perform.

  c) The std idiom for looping thru an array does not necessarily result in
     redundent checks; some modern JVM implementations optimize them away.



Item 40. Use checked exceptions for recoverable conditions and
         run-time exceptions for programming errors

  1) Use checked exceptions for conditions from which the caller can reasonably be expected to recover.

  2) Use run-time exceptions to indicate programming errors

  3) All the unchecked throwables you implement should subclass RuntimeException (directly or indirectly)


Item 41. Avoid unnecessary use of checked exceptions

  When your method throws a checked exception, you force the user to take a decision:
either catch and process the exception, or propagate it outward.  Either way, it places
a non trivial burden on the programmer who uses the method.

  The burden is justified if:
   a) the exceptional conditional cannot be prevented by the proper use of
      the API (e.g. a file is missing, etc.)
   b) AND the programmer using the API can take some useful action once confronted
    w/ the exception.

 If the two conditions are not met, throw an unchecked exception

Item 42. Favor the use of standard exceptions

  One of the attributes that most strongly distinguishs expert programmers from less
experienced ones is that excepts strive for and usually achieve a high degree of code
reuse.  Exceptions are no exception to the general rule that code reuse is code:

  "Reuse standart exceptions i/o defining your own ones"

  E.g:

  Use IllegalArgumentException     if parameter value is inappropriate
  Use IllegalStateException        if object state is inappropieate for method invocation
  Use NullPointerException         if parameter value is null while prohibited
  Use IndexOutOfBoundException     if index parameter is out of range
  ConcurrentModificationException  if concurrent modif of obj has been detected while prohibited
  UnsupportedOperationException    if object does not suppory method


Item 43. Throw exceptions appropriate to the abstraction

  Higher layers should catch lower-level exceptions and,in their place, throw exception
that are explainable in terms of the high-level abstraction, which is called "exception translation"

  Example (from the List interface in JDK) :

  public Object get(int index) {
    ListIterator i = listIterator(index);
    try {
      return i.next();
    } catch (NoSuchElementException e) {
      throw new IndexOutOfBoundException(...);  //translate exception
    }

  Note: Java 1.4 supports "exception chaining"

  Throwable(Throwable t)

  //exception chaining in JDK 1.4
  HigherLevelException(Throwable t) {
    super(t);
  }
 
Item 44. Document all exceptions thrown by each method

  Always declare checked exceptions individually, and document precisely the conditions
under which each one is thrown using the javadoc @throws tag.

  Use the Javadoc @throws tag to document each unchecked exception that a method can throw,
but do not use the throws keyword to include unchecked exceptions in the method declaration.

  If an exception is thrown by many methods i na class for the same reason, it is
acceptable to document the exception in the class' doc comment.


Item 45. Include failure-capture information in detail messages

  exception.toString() typically consists of the exception name followed by its
detail mesage.  Detail messages is info that programmers or field service personnel
investigating a s/w failure will have to go (not for end-user).

  To capture the failure, the string representation of an exception should contain the values
of all parameters and fields that "contributed to the exception".  For instance, the
detail message of an IndexOutOfBoundsException should contain the lower bound, the upper
bound and the actual index. This info tells about the failure.

  One way to ensure that exceptions contain adeqaute failure-capture info in their
string representations is to require this info in their constructors in lieu of the string
detail message:

  public IndexOutOfBoundsException (int lower, int upper, int index) {
    super("low=" + lower + ", upper=" ..
  }

  Unfortunately, the Java platform libs do not make heavy use of this idiom, but
it is highly recommended.



Item 46. Strive for failure atomicity

  Generally speaking, a failed method invocation should leave the obj in the state
it was in prior to the invocation; a method w/ this property is said to be "failure atomic"

   They are several way to achieve failure atomicity:

   1) If the obj is immutable, failure atomicity is free.

   2) For methods altering a mutable obj, the most common way to achieve
      failure atomicity is to check parameters/state for validity before
      performing the operation:


  class Stack {

    public Object pop() {
      if (size == 0) {
         throw new EmptyStackException();  //fail and keep the obj untouched
      }

      Object result = elements[--size]; //affect the obj state
   }

   3) A 3rd and far less common approach to achieving failure atomicity is to
      write "recovery code" that intercepts a failure occurring in the midst of an operation
      and causes the obj to rll back its state to the point before the operation
      began.

   4) A final approach is to perform the operation on a temporary copy of the object and
      replace the contents of the object w/ the temporary copy once the operation is complete.
      For example, Collections.sort() dumps its input list into an array prior to sorting.

Item 47. Don't ignore excpetions
 
    //empty catch block ignores exception: highly suspect
    try {
      ..
    } catch (SomeException ex) {
     
    }

    Empty catch block  is analogous to remove batteries from a fire alarm device.
    If an alarm occurs, this is a reason..

    At the very least, the catch block should containe a comment explaining why it is
appropriate to ignore the exception.
   
 
9-THREADS

Item 48. Synchronize access to shared mutable data

  synchrnization:

  a) prevent an obj from being observed in an inconsistent state while it is modified
     by another thread.
  b) it also ensures that objects progresses from consistent state to consistent state by an
     orderly sequence of state transistions that appear to execute sequentially.

  Java language guarantees theat reading or writing a single variable is atomic unless the
varaiable is lng or double.

  //broken
  class Accounts {
    int checking;
    int savings;

    void transitCheckingToSavings(int amount) {
      checking -= amount; //accounts not in a consistent state here
      savings += amount;  //accounts return in a consistent state here
    }

    int getTotalBalance() {
      return checking + savings;
    }

  //let suppose this sequence of operations:
  THREAD 1 : checking -= amount;        //1st instruction of transitCheckingToSavings()
  THREAD 2 : return checking + savings; //oops, the amount is missing
  THREAD 1 : savings += amount;         //2nd instruction of transitCheckingToSavings()

  fix:
    synchronized void transitCheckingToSavings() {..
    synchronized int getTotalBalance() { ..

  more subtle:

  private static int nextID = 0;

  public static int generateID() {
    return nextID++;
  }

  nextID++ is a read AND write operation, executed sequentially. nextID++ is not atomic.
 
  Thread 1 can get: 0, 1, 1, 3, 4..

  fix:
    public static synchronized int generateID() {


  A correct singleton impl:
 
  private static Singleton() {}

  public static synchronized getInstance() {
    //if single instance not created, do it now

    return singleInstance;
  }   

Item 49. Avoid excessive synchronization

  To avoid the risk of deadlock, never cede control to the client within a synchronized method or block

  As a rule, you should do as little work as possible inside synchronized regions.

Item 50. Never invoke wait() outside a loop

  synchronized(obj) {
 
    while (condition) {
       obj.wait();
    }

  Always use the wait loop idiom to invoke the wait() method


Item 51. Don't depend on the thread scheduler

  Any program that relies on the threat scheduler for its correctness or performance is likely
to be nonportable.

  Resist to the temptation to "fix" the program byputting in calls to Thread.yield()

  The only use that most programmers will ever have for Thread.yield() is to artificially
increase the concurrency of a program duting testing.

Item 52. Document thead safety

  To enable safe multithreaded use, a class must clearly document in prose the level
of thread safety that is supports.

  Level of thread safety:

  Immutable: Thread-safe by default Example: string, Integer.

  Thread-safe: instances of this class of mutable, but all methods contained sufficicient
    internal synchro that instances may be used w/o the need for external synchro.
    Example: java.util.Timer.

  Conditionally thread-safe: Like thread-safe, but contains methods that require external synchro.
    Example: Vector, Hashtable are thread-safe, but iterators require external synchro.

  Thread-Compatible: Required external synchro. Example: arrayList, HashMap

  Thread-Hostile: not safe for concurrent use. Luckily, there are
    few thread-hostile classes in std libs.   Example: System.runFinalizersOnExit();

 
Item 53. Avoid thread groups

  Thread group are largely obsolete.

10-SERIALIZATION

Item 54. Implement Serializable judiciously 

  implementing Serializable involves the following costs:

  1) it decreases the flexibility to change a class' impl once it has been released.

  2) it increases the likelihood of bugs and security holes.

  3) it increases the testing burden associated w/ releasing a new version of a class.

  4) is not a decision to be undertaken hightly
 
  5) classes designed for inheritance should rarely implement serializable, ans interfaces
     hould rarely extend it.

  6) you should provide a parameterless constructor on nonserializable classes designed for inheritance.

  7) inner classes should rarely, if ever, implement Serializable
 
Item 55. Consider using a custom serialized form

  Do not accept the default serialized form w/o first considering whether it is appropriate

  The def serialized form is likely tio be appropriate if an obj's physical rep is identical
  to its logical content.

  Ever if you decide that the def serialized form is appropriate, you often must provide a
  readObject() method to ensure invariants and security

  Using the def serialized form where an obj's physical rep differs substantially from its
logical data content has four disadvantages:

  1) It permanently ties the exported API to the internal rep.

  2) It can consume excessive space

  3) It can consume excessive time

  4) It can cause stack overflow
 
Item 56. Write readObject() methods defensively

  When an obj is deserailized, it is critical to defensively copy any field containing
an obj ref that a client must not possess.

Item 57. Provide a readResolve() method when necessary

  A readResolve() method is necessary not only for singletons, but for all other instance-controlled classes.

  A second use for the readResolve() method is as a conservative alternative to defensive readOnly() recommended in Item 56.

  While the defensive readResolve() idiom is not widely used, it merits serious considerations.

  The accessibility of the readResolve() method is significant.






Dernière mise à jour: 26 novembre 2009.