十二、 可恶的空指针异常
NullPointException是一个常见的错误,由于NullPointException是non-checked Exception所以它总是隐式的出错,无需要我们人为的去捕获。产生NullPointException,它又没有相关的有用的帮助信息,所以很难以跟踪。我们只能通过一些编程标准来减少它在运行时出现的次数。
1. 处理空值的原则:
a. 没有充分的依据,永远都不要假设对象在某一时刻不可能为空。
b. 假如认为空值是一个错误的代码调用,则应该以文字说明。不要让它简单的抛出NullPointException;而是要记录为业务异常,并有直接的异常说明。
c. 通常对方法参数进行空值检查。
2. 在页面参数传递中正确的对待空值和空串
Web编程是无状态编程,web页面只能传递字符串给后台。通常后台程序在获取页面参数的时候要进行特殊字符处理,去掉字符串两端的空格,制表格等特殊字符。
从页面获取的参数如果是空串应该认为它是空值。
典型的处理如下:
3. 正确处理从页面参数传递后把字符串转换为非字符串类型1String s = (String)request.getParameter(name); 2if(s != null ) ...{ 3s = s.trim(); 4} 5 6if("".equals(s)) ...{ 7s = null; 8} 9
我们通常需要获取页面参数并转换为非字符串类型。一般是数值或日期类型。
这需要有两个步骤:
第一步是从页面获取字符串参数,如果是空串则要变为空值
第二步是把字符串转为相应的类型。
例如:从页面获取一个年龄的参数。
在太多的项目中有这样的代码出现,能够正常编译通过。1Stirng ageStr = request.getParameter(“age”); 2if(ageStr != null)...{ 3ageStr = ageStr.trim(); 4} 5 6if(“”.equals(ageStr))...{ 7ageStr = null; 8} 9 10Int age = Integer. parseInt(ageStr); 11
但如果页面的age参数是一个录入域,可以由用户随便录入。并且在页面可能没有做相应完整的javascript控制的时候,很容易 就输入了一些不能进行转换为整数的非法字符串。Integer.parseInt()就会抛出NumberFormaterException.
同样的情况也会出现在日期转换中。
SimpleDateFormat format = new SimpleDateFormat(“yyyy-MM-dd”);
format. Parse(dateStr);
这也有可能抛出ParseException
NumberFormaterException和parseException都是non-checked Exception。都不需强迫用户去处理。不知不觉就会让系统报异常,使得系统十分脆弱。
像这种异常我们应该手动去处理,处理方法有两种:
1. 把异常当空值处理,凡是报这种异常我都把它处理为空值。
3. 编写辅助类来处理页面参数1Date birthday; 2SimpleDateFormat format = new SimpleDateFormat(“yyyy-MM-dd”); 3try...{ 4birthday= format.parse(dateStr); 5}catch(ParseException e)...{ 6birthday = null; 7} 82. 把异常当输入错误处理,应该把相应的提示信息返回输入页面,要求用户重新输入合法的数据 9Date birthday; 10SimpleDateFormat format = new SimpleDateFormat(“yyyy-MM-dd”); 11String errorMessage = null; 12try...{ 13birthday= format.parse(dateStr); 14}catch(ParseException e)...{ 15errorMessage = “日期必须为yyyy-MM-dd格式” 16} 17ModelAndView mav = null; 18if(errorMessage != null)...{ 19mav = new ModelAndView(“inputView”); 20mav.addObject(“error”,errorMessage); 21} 22 23
1public class ServletRequestUtils ...{ 2 3public static final String DEFAULT_DATE_FORMAT="MM/dd/yyyy"; 4 5public static String getStringParameter(HttpServletRequest request, String name) ...{ 6String s = (String)request.getParameter(name); 7if(s != null ) ...{ 8s = s.trim(); 9} 10 11if(s == null || "".equals(s)) ...{ 12return null; 13}...{ 14return s; 15} 16} 17 18public static String getStringParameter(HttpServletRequest request,
String name, String defaultValue) ...{ 19String s = (String)request.getParameter(name); 20if(s != null ) ...{ 21s = s.trim(); 22} 23 24if(s == null || "".equals(s)) ...{ 25return defaultValue; 26}...{ 27return s; 28} 29} 30 31public static Date getDateParameter(HttpServletRequest request, String name)
throws BusinessException ...{ 32String dateString= getStringParameter(request,name); 33SimpleDateFormat format = new SimpleDateFormat(DEFAULT_DATE_FORMAT); 34try ...{ 35if(dateString != null && !"".equals(dateString)) ...{ 36return format.parse(dateString); 37}else ...{ 38return null; 39} 40}catch(ParseException e) ...{ 41throw new BusinessException("无效的日期输入:格式错误:"+dateString); 42} 43} 44 45public static Date getDateParameter(HttpServletRequest request ,
String name, String dateFormat)throws BusinessException...{ 46String dateString= getStringParameter(request,name); 47SimpleDateFormat format = new SimpleDateFormat(dateFormat); 48try ...{ 49if(dateString != null && !"".equals(dateString)) ...{ 50return format.parse(dateString); 51}else ...{ 52return null; 53} 54}catch(ParseException e) ...{ 55throw new BusinessException("无效的日期输入:格式错误:"+dateString); 56} 57} 58 59public static Date getDateParameter(String dateStr)throws BusinessException...{ 60 61SimpleDateFormat format = new SimpleDateFormat(DEFAULT_DATE_FORMAT); 62try ...{ 63if(dateStr != null && !"".equals(dateStr)) ...{ 64return format.parse(dateStr); 65}else ...{ 66return null; 67} 68}catch(ParseException e) ...{ 69throw new BusinessException("无效的日期输入:格式错误:"+dateStr); 70} 71} 72 73public static Date getDateParameter(String dateStr,String dateFmt)
throws BusinessException...{ 74 75SimpleDateFormat format = new SimpleDateFormat(dateFmt); 76try ...{ 77if(dateStr != null && !"".equals(dateStr)) ...{ 78return format.parse(dateStr); 79}else ...{ 80return null; 81} 82}catch(ParseException e) ...{ 83throw new BusinessException("无效的日期输入:格式错误:"+dateStr); 84} 85} 86} 87