21 May, 2012

Avoid Null Pointer Exception Part 2


I present in previous post Avoid Null Pointer Exception part 1 some best practice regarding my topic today, I will continue in providing more best practice and advices.

In part 1 post I listed how to avoid NPE in equalsIgnoreCase() method and enumerator, today I will write about below cases
1- Empty Collection
2- Use some Methods
3- assert Keyword
4- Assert Class
5- Exception Handling
6- Too many dot syntax
7- StringUtils Class

1- Empty Collection
Empty collection is collection which hasn't any elements. Some developers return null value for Collection which has no elements but this is false, you should return Collections.EMPTY_LIST, Collections.EMPTY_SET and Collections.EMPTY_MAP.

Wrong Code
   public static List getEmployees() {  
     List list = null;  
     return list;  
   }  

Correct Code
   public static List getEmployees() {  
     List list = Collections.EMPTY_LIST;  
     return list;  
   }  

2- Use some Method 
Use some methods to assure that null value not exist like contains(), indexOf(), isEmpty(), containsKey(), containsValue() and hasNext().

Example
     String myName = "Mahmoud A. El-Sayed";  
       
     List list = Collections.EMPTY_LIST;  
     boolean exist = list.contains(myName);  
     int index = list.indexOf(myName);  
     boolean isEmpty =list.isEmpty();  
       
     Map map =Collections.EMPTY_MAP;  
     exist=map.containsKey(myName);  
     exist=map.containsValue(myName);  
     isEmpty=map.isEmpty();  
       
     Set set=Collections.EMPTY_SET;  
     exist=set.contains(myName);  
     isEmpty=set.isEmpty();  
       
     Iterator iterator;  
     exist = iterator.hasNext();  


3- assert Keyword
assert is keyword provided in Java 1.4 which enables you to test your assumptions about your code.

Syntax of assert keyword
 assert expression1 ;  
expression1 is boolean expression which is evaluated and if it is false system will throw AssertionError with no detail message

 assert expression1 : expression2 ;  
expression1 is boolean expression which is evaluated and if it is false system will throw AssertionError and detail message is expression2

For example in my post I want to assert that expression is not null then I should write below code
   public static String getManager(String employeeId) {  
     assert (employeeId != null) : "employeeId must be not null";  
     return "Mahmoud A. El-Sayed";  
   }  

If I try to call getManager method using getManager(null);
It will raise  "java.lang.AssertionError: employeeId must be not null"

Note use -enableassertion in your java option while run your code to enable assertion.

4- Assert Class
Assert class exists in com.bea.core.repackaged.springframework.util package and has a lot of methods used in assertion.

Example
   public static String getManager(String employeeId) {  
     Assert.notNull(employeeId, "employeeId must be not null");  
     Assert.hasLength(employeeId, "employeeId must has length greater than 0");  
     return "Mahmoud A. El-Sayed";  
   }  

If I try to call getManager method using getManager(null);
It will raise  "java.lang.IllegalArgumentException: employeeId must be not null"

5- Exception Handling
I should take care in exception handling using try catch statement or checking of null value of variables
For example
   public static String getManager(String employeeId) {  
     return null;  
   }  

I will cal it using below code
     String managerId = getManager("A015");  
     System.out.println(managerId.toString());  

It will raise "java.lang.NullPointerException" , so to handle this exception I should use try catch or checking of null values

a- try catch statement
I will change calling code to below code
     String managerId = getManager("A015");  
     try {  
       System.out.println(managerId.toString());  
     } catch (NullPointerException npe) {  
       //write your code here  
     }  

b- Checking of Null values
I will change calling code to below code
     String managerId = getManager("A015");  
     if (managerId != null) {  
       System.out.println(managerId.toString());  
     } else {  
       //write your code here  
     }  

6- Too many dot syntax
Some developers use this approach as he writes less code but in the future will not be easier for maintenance and handling exception

Wrong Code
 String attrValue = (String)findViewObject("VO_NAME").getCurrentRow().getAttribute("Attribute_NAME");  

Correct Code
     ViewObject vo = findViewObject("VO_NAME");  
     Row row = vo.getCurrentRow();  
     String attrValue = (String)row.getAttribute("Attribute_NAME");  

7- StringUtils Class
StringUtils class is part of org.apache.commons.lang package, I can use it to avoid NPE specially all its methods are null safe
For example StringUtils.IsEmpty(), StringUtils.IsBlank(), StringUtils.equals(), and much more.
You can read specification of this class from here


Conclusion
Always take care of  NullPointerException when writing code and guess how it will be thrown in your code and write //TODO in your code for solving it later if you haven't more time.

Thanks

10 comments:

  1. Thanks a lot for shairing such usefull information.

    ReplyDelete
  2. every where that a new object is created try and use the NullObject pattern and return a new object as you should be programming to interfaces and then there is no need to do all the null , exception checking

    ReplyDelete
    Replies
    1. Thanks for sharing this good approach "NUll Object Pattern"
      I should add it to the article because it is good approach

      Delete
  3. You should only return Collections.EMPTY_LIST and its cognates if the client is not allowed to change the returned value. However, in that case the method is flawed anyway. Take the first:

    public static List getEmployees() {
    List list = null;
    return list;
    }

    Now you should be using JDK 1.5 or higher by now, and using generics; the method would return List<Employee>. The method should not be static either; suppose it is in a Department class. Do you expect to have only one Department and one list of employees?

    public class Department {
    private List<Employee> employees = new ArrayList<Employee>();
    public List<Employee> getEmployees() {
    return employees;
    }
    }

    Now, the method does not return null. Protecting the setter method is easy:

    public void setEmployees(List<Employee> newEmployees) {
    if (newEmployees != null) {
    employees = newEmployees;
    } else {
    employees = new ArrayList<Employee>();
    }
    }

    Now, nothing should be able to set employees to null. However you now have a different danger, aliasing. You can have code like:

    Department dept = ...;
    List<Employees> emps = dept.getEmployees();
    emps.clear();
    System.out.println(emps.getEmployees().size()); // Prints 0. Everybody has been fired.

    So, you need to copy the list in the get method, and in the set method:

    public void setEmployees(List<Employee> newEmployees) {
    if (newEmployees != null) {
    employees = new ArrayList<Employee>(newEmployees);
    } else {
    employees = new ArrayList<Employee>();
    }
    }

    You may want to use a more sophisticated collection than ArrayList, one that also does not allow null entries.

    ReplyDelete
  4. Or use Guava Optional class.

    ReplyDelete
  5. Thanks nice post.

    I know some fool technical leads who force developers to use much dot operators for clarity of code. Clarity is essential, But not this way.

    ReplyDelete
  6. From my experience as a support of huge legacy code I can just tell that Null Pointer exception is one of the best bugs that you can get to fix. When investigating null pointer exception you take the stack-trace, get to the source of the problem and usually immediately see where is the problem. I seriously don't understand why peeps hate Null Pointer exception.

    ReplyDelete
  7. You should remove '6 - Too many dot syntax' as it does not prevent NPE

    ReplyDelete
    Replies
    1. Too many dot syntax is not direct reason of NPE, but if any member function is called from super class has Null value will yield NPE

      Delete

ADF : Scope Variables

Oracle ADF uses many variables and each variable has a scope. There are five scopes in ADF (Application, Request, Session, View and PageFl...