Tuesday, December 12, 2017

Effective Java Extracts

I have documented for my learning purpose ideas from the book Effective Java [0] by Joshua Bloch. I have documented every idea with a minimal example. The book contains tons of valuable information that might be absent in this series of articles.


0. Prefer a Static Method instead of Constructors
Example:
public static Boolean valueOf(Boolean b){
return b? Boolean.TRUE : Boolean.FALSE
}


Advantages of static method to construct objects:
a. does not always create a new object
b. provides more information than constructor overloading
BigInt(prm1, prm2) //this constructor's purpose is to return a relative prime compared to static getRelativePrime(prm1, prm2) //static constructor has descriptive name

c. a subclass can be returned


Disadvantages
a. classes without public constructors cannot be subclassed
b. static object generator methods are hard to distinguish from other methods.
workaround, use well established static method names for object generation
- valueOf
- getInstance


1. Enforce Singleton Property with a Private Constructor

class Elvis{
  private final INSTANCE = new Elvis();
  private Elvis(){}
  public static getInstance(){ return INSTANCE; }
}


2. Prevent Instance Creation with Private Constructor
This tip is applicable for utility classes that only have collection of static methods, such as Math class.
class Math{
  private Math(){
    //constructor is private so not possible to create instance Math class
  }
}

3. Avoid Creating Duplicate Objects
//Don't do this
public void isBornOn90s(){
  calendar = Calendar.getinstance()
  calendar.setDate(1, 1, 1990)
  startDate = calender.getDate()
  calendar.setdate(12, 31, 1999)
  endDate = calendar.getDate()

  if(this.birthDate.after(startDate) && this.birthDate.before(endDate)) 
    return true 
  else return false
}


instead create those date objects as private member
Person{
  private startDate;
  private endDate;

  static{
    calendar = Calendar.getinstance()
    calendar.setDate(1, 1, 1990)
    startDate = calender.getDate()
    calendar.setdate(12, 31, 1999)
    endDate = calendar.getDate()
  }

  public void isBornOn90s(){
    return bithdate.after(startDate) && birthdate.before(endDate);
  }
}


4. Get rid of Objects that will not be Referenced Again
Memory leak is a situation when we keep storing objects that won't be referenced any more.

Stack{
  elements = new elements();

  push(item){
    //if no more space then allocate space and copy old items to new space
    //....
    elements[size++] = item
  }

  pop(){
    return elements[--size];
  }
}

The problematic line is in the pop method, it does not discards a popped item. The method needs to
be rewritten as the following

pop(){ res = elements[--size] elements[size] = null return res }

Good practices:
a. declare variables in narrowest possible scope so that scope discards the variable automatically.
b. set unnecessary reference to null.

5. Do not Use Finalzer methods
Every object has a finalize method, that is expected to be called when the 
object is being garbage collected. Problem is JVM does not guarantee that the
 "finalize" method will get called. So resources might never be released if 
 finalize methods are used.

//Don't do this
Class WrongWay{
  private resourceA, resourceB;

  //it is unknown if the following method will be called or not by GC
  finalize(){
    release resourceA
    release resourceB
  }
}

//Do this
class RightWay{
  private resourceA, resourceB;

  //provide method that acquires resources
  acquire(){
    acquireResource resourceA
    acquireResource resourceB
  }

  //provide method to release methods. Users should call this mehtod explicitly.
  release(){
    release resourceA
    release resourceB
  }
}

Almost always it is bad to use finalizers. It can be used to provide a safety 
net incase the users of the api forgets to call close method. Then another 
problem arises. From overridden finalize method, we will have to call 
super.finalize() explicitly otherwise that method won't get called. A better 
way is the following

class SafetyNetFinalize{
  private saftety = new Object{
    finalize(){
      SafetlyNetFinalize.this.finalize()
    }
  }
}

This works because the SafetyNetFinalize does not override finalize method, so
no fear that it's implementation forgets super.finalize() method



No comments:

Post a Comment