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
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 expression2For 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
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 variablesFor 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 exceptionWrong 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 safeFor example StringUtils.IsEmpty(), StringUtils.IsBlank(), StringUtils.equals(), and much more.
You can read specification of this class from here
Conclusion
Thanks
Excellent
ReplyDeleteThanks a lot for shairing such usefull information.
ReplyDeleteevery 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
ReplyDeleteThanks for sharing this good approach "NUll Object Pattern"
DeleteI should add it to the article because it is good approach
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:
ReplyDeletepublic 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.
Or use Guava Optional class.
ReplyDeleteThanks nice post.
ReplyDeleteI know some fool technical leads who force developers to use much dot operators for clarity of code. Clarity is essential, But not this way.
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.
ReplyDeleteYou should remove '6 - Too many dot syntax' as it does not prevent NPE
ReplyDeleteToo 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