EffectiveJava Notes
valueOf()
//Return an instance of which same value as passed value. This method noramly used for type conversion.
//Example
//Returns Integer equevalent to passed integer
Interger.valueOf(String intValue)
//Method
of()
//A consice alternative of valueOf() method, popularly used for EnumSet.
//Example
EnumSet<Color> yellow = EnumSet.of(Color.RED, Color.GREEN);
//Method
getIntance()
//Get intance build by using passed paramter, but can not said have same value as passed.
//It may be do some conversion before build intance.
//If it used for Singleton then, it will not take any parameter.
//Example
Connection.getInstance()
//Method
newIntance()
//Return always new instance based on passed paramter.
//Example
Connection.newInstance(String url)
//Method
getType()
//This metohd is like getIntance(), except it will return Object of type.
//Example
List<String> list = CSVFile.getList()
//Method
newType()
//This method is like newInstance() return type object as metioned in method name.
//Example
Context context = HttpServeletRequest.getContext()- Always define strategy interface, to allow diffrent startegy of same type
- Strategy Object in same for multiple call, consider to make it singletone.
- If it object is used only once, then consider using anonymous class of strategy.
- Comparator from java.util package
public Comparator<T> {
int compare(T o1, T o2);
}- Always check method paramter, document what happen if when method get invalid parametr.
- If not checked replace with it good document about it.
- If not document or not checked it is very hard do determine to detect cause.
- Sometime need to debug code to find cause.
- When not sure about client of code may change state of mutable state, consider to make defensive copy.
- Try not to consider clone methode while making defensive copy, it has its own side effect.
- In singleton, make sure you make copy of reference instance mutable variable properly.
- While checking condition mutable refernce, make sure you first clone then check.
- By checking first condition then clone may change mutable variable state.
- Following example shows TIME OF CHECK|TIME OF USER (TOCTOU) attack
//Broken !!!!
public void setDOB(Date dob) {
Date now = new Date();
if(now.compaireTo(dob) < 0) {
throws new IllegalArgumentException("DOB must less than than cuurrent date");
}
//Make Defensive copy, But after check client make changes in passed dob reference copy
this.dob = new Date(dob.getTime());
}
//Correct first We make defensive copy then check for condition
public void setDOB(Date dob) {
Date now = new Date();
//Make Defensive copy
this.dob = new Date(dob.getTime());
if(now.compaireTo(dob) < 0) {
throws new IllegalArgumentException("DOB must less than than cuurrent date");
}
}- Choose method name carefully, which must follow you package naming convention.
- Primary goal is to make it readable, understandable, easy to guesse about methods funtionality.
- Avoid long list parameters. Avoid long list method parameter, it is verey hard to remember once list is long.
- Long list make programmer force to see documention, even it is very hard when metod paramter has same type.
- Ways to avoid long parametr are
- Builder Pattern (While Conctructing Factory methods)
- Holder Static class
- Telescopic pattern (Least preferd)
- For parameter type favor intefaces over classes. By doing this you are forced to client to pass specific implemetation.
- It helps to client to avoid type conversion, if data is in differ format.
- Prefer Enum type to boolean Parameter. It make you code more readable and writable if IDE support autocompletion for enum.
- Also it helps add more Option for future need.
- Following example shows Thermometer static factory which takes its scale using boolean and Using enum
// Thermometer with two scale isFarenheit (true), CELSIUS(false) Thremometer.newInstance(true); //With Enum enum ThermometerScale { FARENHEIT, CELSIUS } //More Readable, and add more option scale if required Thremometer.newIntance(ThermometerScale.FARENHEIT);
- Overloading is determined at compile time.
- So whatever type know at compile time is considered for method invocation .
- When writing API make sure it is not confusing for radical diffrence type paramter, we can't guess which should get call.
- Better choice for overloading is to use properNamed method instead of overload.
- Thumb rule is Never overload a method with same numbers of parameter(Radically same).
- Following Example shows confusing code
public void print(Set<String> c) { System.out.println("Set"); } public void print(List<String> c) { System.out.println("List"); } public void print(Collection c) { System.out.println("Unknown Collection"); } public static void main(String[] args) { Collection[] collections = {new HashSet(), new ArrayList()} for(Collection c : collections) { print(c); // Always print "Unknown Collection", compile time know type is Collection } }
- Alaways take care while calling overload method which may involved autoboxing.
- Following example shows autoboxing issue
List<Integer> lsInterger = new ArrayList(); for(int i =-2; i<3;i++) { lsInterger.add(i); } for(int i=0; i<2;i++) { lsInteger.remove(i);//It removes o 1 2 instead of -2 -1 0 //i is boxed to Interger an overloaded method remove(E) is called instead remove(index) }
- Java 1.4 added varargs.
- Use varags when input length is unknown to method.
- Using varargs we cant force user to pass at least require data, don't use varags in this condition.
- Consider following examples , shows good and bad code.
public Map<String,String> getPersonAttribute(String... args) { String id = args[0]; //Must required ...... } //Instead use following way public Map<String,String> getPersonAttribute(String personId, String... args) { ...... }
- There is cost for creation of array for each varargs even you are passing one argument.
- If it sure and require minimum paramter, don't pass it using varagrs.
- Example shows a correct way to handle above sentence
//Not Best way public void method(String... args) { String req_1 = args[0]; String req_2 = args[0]; //Don with remainign if provided } //Best way, if not given any varargs argument , we avoide cost of creation of array public void method(String req_1, String req_2, String... args) { }
- Always return Empty array or collection instead of null,it will avoid client code to take care of null return.
- If developer forgot to handle such case, it may cause NullPointerException Or developer has to check document about method returns.
- For collection use
java Collections.emptyList(),like collection methods.
-
If API is usable, always document it using java doc commects (```java /** Doc comment*/).
-
Write doc comment for every exported class, method, constructor, field.
-
If class is serializable, we should also document its serializable form.
-
The doc comment for a method should describe the contract between method and its client.
-
Doc should says what method does rather than how it does.
-
Doc of method should specify percondition , postcondition and side effect.
-
Finally add thread safety of class and method.
-
How to write document for method
- To define methods contract fully, method should use
- @param for parameter, should not terminate with period
- @return for return value, should not terminate with period
- @throws if methods thorws any Exception, should not terminate with period
- {@code} to write code, instead use HTML code tag.
- {@inheritDoc} to inherit doc from class or interface.
- {@literal} to avoid processing of HTML element (<, > brackets)
- First line should explain what method does and end with period.
- Following first line with end period ,write detail paragraph using p tag without end of it.
- @return and @param tag shoud have noun after them
/** * Return element at spefied index from list. * <p>This method in <i>not</i> guarantee to run in constant time, in some implementation it may propotional * size of list. * * * @param index index of element to return; must be positive number * And should be in list range * @return the element at specified index from this list * @throws IndexOutOfBoundsExceptions if specified index is not in range of list. */ E get(int index);
-
No two class constructor or interface method with same number of parameter have same first description line.
-
When documenting Enum make sure, to document each constant.
/** * Colors of TV */ public Enum TvColor { /*** Indicate green color of TV */ GREEN , /*** Indicate blue color of TV */ BLUE; }
-
When using generic for method or class , make sure you document all type.