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){
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
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
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
}
}
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
}
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);
}
}
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 }
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
}
}
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