Java中空指针异常该如何避免详解

Java中如何避免空指针异常,这也是由初级程序员成长到中级程序员的时候经常会遇到的问题。

程序员不知道或不信任正在使用的约定,并且小心的检查着null。还有当程序员写代码的时候,总是会依赖于通过返回空(NULL)来表明某些意义,因此需要调用者去检查Null。

有两种空指针的检查场景:

  • 期望的结果就是null。
  • 期望的结果不是null。

第二种很简单,可以通过用assert或者允许程序报错,例如抛出NullPointerException。Assertions是一个从Java1.4加进来的高度未被利用的特性,语法是:

assert <condition>

或者

assert <condition> : <object>

condition是一个布尔表达式,object是一个对象(其toString()方法的输出将会被包含在错误里)。

校对注:我测试了下,JDK1.4及其以上,运行前设置vm参数-ea

public static void main(String[] args) {String name = null;assert (name != null) : "name为空null";}
Exception in thread "main"; java.lang.AssertionError: 变量name为空nullat LogUtil.main(LogUtil.java:37)

如果condition为false的话,assert将会抛出一个Error(AssertionError)。默认Java会忽略断言你可以通过在JVM中传入一个-ea参数来启用断言。

你可以为单独的一个包或者类启动关闭assertions。这意味着你可以在开发和测试的时候通过断言来验证代码,在发布产品的时候关闭它,尽管我下面展示的测试中并没有因为assertions而损失性能。在这个代码段中不用断言也可以,因为他会运行失败的,就像加了断言一样。唯一的区别是有了断言可能会发生的更快一些,更有意义,并且会附加一些额外的信息,而这可以帮助你弄明白失败的原因。

第一种有一点棘手。如果你对不能控制正在调用的这段代码,那你就卡住了。如果Null是一个合理的返回值,你就应该检查它。如果是你能够控制的代码,那就是个完全不同的故事情景了。尽量避免用NULL作为返回值。对于返回Collections的集合很容易,返回Empty(一个空集合或者数组),而不是一直用null作为返回值。对于不是返回Collections的方法会有一点复杂。考虑下面这个例子:

public interface Action {
  void doSomething();}public interface Parser {
  Action findAction(String userInput);}

Parser采用用户的输入作为参数,然后做一些事情(例如模拟一个命令行)。现在你可能会返回null,如果没找到对应输入的动作的话,这就导致了刚才说过的空指针检查。

一个可选的解决方案是永远不要返回null,而是返回一个空对象

public class MyParser implements Parser {
  private static Action DO_NOTHING = new Action() {
    public void doSomething() { /* do nothing */ }
  };

  public Action findAction(String userInput) {
    // ...
    if ( /* we can't find any actions */ ) {
      return DO_NOTHING;
    }
  }}

比较这段代码:

Parser parser = ParserFactory.getParser();if (parser == null) {
  // now what?
  // this would be an example of where null isn't (or shouldn't be) a valid response}Action action = parser.findAction(someInput);if (action == null) {
  // do nothing} else {
  action.doSomething();}

和这段:

ParserFactory.getParser().findAction(someInput).doSomething();

这是个更好的设计,因为足够简洁,避免了多余的判断。

即便如此,或许比较合适的设计是:findAction()方法之恶杰抛出一个异常,其中包含一些有意义的错误信息—–特别是在这个案例中你依赖于用户的输入。

让findAction()方法抛出一个异常而不是简单的产生一个没有任何解释的NullPointerException 要好得多。

try {
    ParserFactory.getParser().findAction(someInput).doSomething();} catch(ActionNotFoundException anfe) {
    userConsole.err(anfe.getMessage());}

或者你认为try/catch 的机制太丑了,你的action应该跟用户提供一个反馈而不是什么都不做:

public Action findAction(final String userInput) {
    /* Code to return requested Action if found */
    return new Action() {
        public void doSomething() {
            userConsole.err("Action not found: " + userInput);
        }
    }}

补充:个人在做项目时,对NullPointerException的几点总结,请网友拍砖!!!多多提意见,

1.对于别人接口的返回对象要做非空判断,因为我们不清楚获得的对象会不会为空,对于Collection Map 我一般会调用CollectionUtils MapUtils ,对于返回的String对象,我会调StringUtils.isNotEmpty()进行非空判断。他们中isNotEmpty不仅判断了NULL 还判断了空集合和空串。例如从数据中查询的结果。工作流中返回的定价URL

2. 对于自己创建的对象,要留心对象进行哪些操作,中间会不会造成对象为空,如果可能加非空判断,尤其是对于集合的操作,很容易就报空指针!!!所以每次对操作集合时,我都会非常的留心。

3. 对于前台的领域对象要非常的留心,因为这些对象是框架创建的,假如我没有在前台的文本框内输入值,虽然提交时后台获得的是空串,但发生NullPointerException的概率很高。

4. 对于String 的操作尽量使用apache 的StringUtils类,与String相比这个是非常的安全。对于集合的操作使用apache的CollectionUtils 、MapUtils, 相比apache工具类的执行效率也非常的高,比如StringUtils.split();

有人说过多的判断会影响性能,我个人认为这里的性能牺牲和系统的安全相比是微不足道的。

总结

到此这篇关于Java中空指针异常该如何避免的文章就介绍到这了,更多相关Java空指针异常内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • Java详细讲解分析双指针法的使用

    目录 前言 1.判断链表是否有环 2.查找链表中间的元素 3.奇偶排序前奇后偶 4.删除排序链表的重复元素 5.三数之和 6.分割链表 7.合并两个有序的数组 8.两数之和—输入有序数组 9.长度最小的子数组 10.排序链表 前言 通常用在线性的数据结构中,比如链表和数组. 指针其实就是数据的索引或者链表的结点.两个指针朝着左右两个方向移动,直到满足搜索条件. 双指针可分为同向双指针.异向双指针.快慢指针.滑动窗口.根据需求选择双指针的模型,比如 删除数组或链表中重复的元素,同向双指针(线性表前

  • java中的空指针异常情况以及解决方案

    目录 概述 问题描述 第一种 第二种 第三种 问题定位 Java空指针异常的若干解决方案 存在NullPointerException的安全方法 如何避免 java空指针异常:java.lang.NullPointException 一.什么是java空指针异常 二.如何解决 概述 出现空指针异常,常常是因为我们调用的对象是空的而抛出的异常. 问题描述 第一种 out.println(request.getParameter("username")); 如果request里面并没有us

  • 教你如何轻松学会Java快慢指针法

    一.什么是快慢指针? 快慢指针就是定义两根指针,移动的速度一快一慢,以此来制造出自己想要的差值.这个差值可以让我们找到链表上相应的节点. 那快慢指针可以解决哪些实际问题呢,接下来我们一起看看吧! 二.使用快慢指针来找到链表的中点 1.首先我们设置两个指针slow和fast,这2个指针的初始位置相同,都指向链表的头结点,然后slow指针每次移动一步,fast指针每次移动两步: 2.如果链表中节点个数为偶数时,当快指针无法继续移动时,慢指针刚好指向中点:如果链表中节点个数为奇数时,当快指针走完,慢指

  • Java中空指针异常该如何避免详解

    Java中如何避免空指针异常,这也是由初级程序员成长到中级程序员的时候经常会遇到的问题. 程序员不知道或不信任正在使用的约定,并且小心的检查着null.还有当程序员写代码的时候,总是会依赖于通过返回空(NULL)来表明某些意义,因此需要调用者去检查Null. 有两种空指针的检查场景: 期望的结果就是null. 期望的结果不是null. 第二种很简单,可以通过用assert或者允许程序报错,例如抛出NullPointerException.Assertions是一个从Java1.4加进来的高度未被

  • Java中JDBC的使用教程详解

    目录 概念 快速入门 步骤 代码实现 详解各个对象 DriverManager:驱动管理对象 Connection:数据库连接对象 Statement:执行sql的对象 ResultSet:结果集对象,封装查询结果 PreparedStatement:执行sql的对象 抽取JDBC工具类 : JDBCUtils 分析 代码实现 练习 JDBC控制事务 事务 操作 使用Connection对象来管理事务 代码 概念 Java DataBase Connectivity  Java 数据库连接, J

  • Java 中This用法的实例详解

     Java 中This用法的实例详解 用类名定义一个变量的时候,定义的只是一个引用,外面可以通过这个引用来访问这个类里面的属性和方法. 那们类里面是够也应该有一个引用来访问自己的属性和方法纳? 呵呵,Java提供了一个很好的东西,就是 this 对象,它可以在类里面来引用这个类的属性和方法.先来个简单的例子: public class ThisDemo { String name="Mick"; public void print(String name){ System.out.pr

  • Java中正则表达式的使用和详解(下)

    在上篇给大家介绍了Java中正则表达式的使用和详解(上),具体内容如下所示: 1.常用正则表达式 规则 正则表达式语法   一个或多个汉字 ^[\u0391-\uFFE5]+$  邮政编码 ^[1-9]\d{5}$ QQ号码 ^[1-9]\d{4,10}$  邮箱 ^[a-zA-Z_]{1,}[0-9]{0,}@(([a-zA-z0-9]-*){1,}\.){1,3}[a-zA-z\-]{1,}$  用户名(字母开头 + 数字/字母/下划线) ^[A-Za-z][A-Za-z1-9_-]+$ 手

  • java 中enum的使用方法详解

    java 中enum的使用方法详解 enum 的全称为 enumeration, 是 JDK 1.5 中引入的新特性,存放在 java.lang 包中. 下面是我在使用 enum 过程中的一些经验和总结. 原始的接口定义常量 public interface IConstants { String MON = "Mon"; String TUE = "Tue"; String WED = "Wed"; String THU = "Thu

  • java 中自定义OutputFormat的实例详解

    java 中 自定义OutputFormat的实例详解 实例代码: package com.ccse.hadoop.outputformat; import java.io.IOException; import java.net.URI; import java.net.URISyntaxException; import java.util.StringTokenizer; import org.apache.hadoop.conf.Configuration; import org.apa

  • java中的interface接口实例详解

     java中的interface接口实例详解 接口:Java接口是一些方法表征的集合,但是却不会在接口里实现具体的方法. java接口的特点如下: 1.java接口不能被实例化 2.java接口中声明的成员自动被设置为public,所以不存在private成员 3.java接口中不能出现方法的具体实现. 4.实现某个接口就必须要实现里面定义的所有方法. 接下来看一个实现接口的案例: package hello;   interface competer{ //定义接口 void set_comp

  • java中Spring Security的实例详解

    java中Spring Security的实例详解 spring security是一个多方面的安全认证框架,提供了基于JavaEE规范的完整的安全认证解决方案.并且可以很好与目前主流的认证框架(如CAS,中央授权系统)集成.使用spring security的初衷是解决不同用户登录不同应用程序的权限问题,说到权限包括两部分:认证和授权.认证是告诉系统你是谁,授权是指知道你是谁后是否有权限访问系统(授权后一般会在服务端创建一个token,之后用这个token进行后续行为的交互). spring

  • Java中正则表达式的使用和详解(上)

    1.匹配验证-验证Email是否正确 public static void main(String[] args) { // 要验证的字符串 String str = "service@xsoftlab.net"; // 邮箱验证规则 String regEx = "[a-zA-Z_]{1,}[0-9]{0,}@(([a-zA-z0-9]-*){1,}\\.){1,3}[a-zA-z\\-]{1,}"; // 编译正则表达式 Pattern pattern = Pa

  • Java中的动态和静态编译实例详解

    Java中的动态和静态编译实例详解 首先,我们来说说动态和静态编译的问题. Q: java和javascript有什么区别?    总结了一下:有以下几点吧: 1.首先从运行环境来说java代码是在JVM上编译成class文件,而javascript则直接在浏览器上加载运行. 2.由第一点可看出,java代码需要编译,而javascript不需要编译. 3.从语言性质来说,java是一种高级编程语言,对变量检查要求严格,javascript只是一个简单的解释性的脚本语言,对变量检查及要求很弱.

随机推荐