【摘自网络】JAVA空指针异常

NPE是指编程语言中的空指针异常

NullPointerException

编程语言中的空指针异常。

当应用程序试图在需要对象的地方使用 null 时,抛出该异常。这种情况包括:

  • 调用 null 对象的实例方法。

  • 访问或修改 null 对象的字段。

  • null 作为一个数组,获得其长度。

  • null 作为一个数组,访问或修改其时间片。

  • null 作为 Throwable 值抛出。

应用程序应该抛出该类的实例,指示其他对 null 对象的非法使用。

来自百度百科:https://baike.baidu.com/item/%E7%A9%BA%E6%8C%87%E9%92%88%E5%BC%82%E5%B8%B8

 

 

出现在任何一个位置上的对象引用都有可能为 null,在进行访问,赋值,取值,类型转换等操作时,首先判断该对象是否为 null,否则极易抛出空指针异常;
  • map.get(key) ⇒ 就有可能 key 不在 map 中;

    • 避免的方法也十分简单,对返回值进行判断;

  • 如果一个函数的返回值为对象的引用,该返回值也可能为空指针;

  • 强制类型转换;

1. 规避手段

  • 使用 object.equals(“test”); 而非 test”.equals(object);

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/lanchunhui/article/details/78209130

 

 

空指针和0NULL之间的关系

1.        什么是空指针常量null pointer constant?

英文定义:

[6.3.2.3-3] An integer constant expression withthe value 0, or such an expression cast to type void *, is called a nullpointer constant.

即:具有0值的整型常量表达式或具有0值的并转换成void *类型的表达式都叫做空指针常量

故,我们可以说00L'/0'3 - 30 * 17 (它们都是“integer constant expression”)以及 (void*)0等都是空指针常量。注意 (char*) 0不叫空指针常量,只是一个空指针值      至于系统选取哪种形式作为空指针常量使用,则与实现相关的。一般的 C系统选择 (void*)0 或者 0 的居多(也有个别的选择 0L);至于 C++ 系统,由于存在严格的类型转化的要求,void* 不能像C 中那样自由转换为其它指针类型,所以通常选 0 作为空指针常量(tyc: C++标准推荐),而不选择 (void*)0

2.        什么是空指针null pointer?

英文定义:

[6.3.2.3-3] If a null pointer constant isconverted to a pointer type, the resulting pointer, called a null pointer, isguaranteed to compare unequal to a pointer to any object or function.

即:如果把一个空指针常量转换成指针,那么这个指针就被叫做空指针。

故,如果 p是一个指针变量,则 p = 0;p = 0L; p = '/0';p = 3 - 3; p = 0 * 17中的任何一种赋值操作之后(对于 C来说还可以是 p = (void*)0;), p都成为一个空指针,由系统保证空指针不指向任何实际的对象或者函数。反过来说,任何对象或者函数的地址都不可能是空指针。

例如:char *p; //定义一个字符指针p

             p=0; // p被初始化为空指针

3.     什么是 NULL
英文定义:
[6.3.2.3-Footnote]The macro NULL is defined in <stddef.h> (and other headers) as a nullpointer constant

即:NULL是一个标准规定的宏定义,用来表示空指针常量

故,除了上面的各种赋值方式之外,还可以用 p =NULL;来使 p成为一个空指针。(tyc:很多系统中的实现:#define NULL (void*)0,与这里的“a null pointer constant”并不是完全一致的)。

注意:使用NULL时必须包含相应的头文件。

4.     空指针(null pointer)指向了内存的什么地方(空指针的内部实现)?
标准并没有对空指针指向内存中的什么地方这一个问题作出规定,也就是说用哪个具体的地址值(0x0
地址还是某一特定地址)表示空指针取决于系统的实现。我们常见的空指针一般指向 0 地址,即空指针的内部用全 0 来表示(zero null pointer,零空指针);也有一些系统用一些特殊的地址值或者特殊的方式表示空指针(nonzero null pointer,非零空指针),具体请参见C FAQ

幸运的是,在实际编程中不需要了解在我们的系统上空指针到底是一个 zero null pointer还是 nonzero null pointer我们只需要了解一个指针是否是空指针就可以了——编译器会自动实现其中的转换,为我们屏蔽其中的实现细节。注意:不要把空指针的内部表示等同于整数 0 的对象表示——如上所述,有时它们是不同的。

5.     如何判断一个指针是否是一个空指针?

这可以通过与空指针常量或者其它的空指针的比较来实现(注意与空指针的内部表示无关)。例如,假设 p是一个指针变量,q是一个同类型的空指针,要检查 p是否是一个空指针,可以采用下列任意形式之一——它们在实现的功能上都是等价的,所不同的只是风格的差别。

转自:https://wenku.baidu.com/view/250567c08bd63186bcebbcc0.html





1,空指针异常产生的主要原因如下:
1)当一个对象不存在时又调用其方法会产生异常:对象不存在
2)当访问或修改一个对象不存在的字段时会产生异常:方法不存在

3)字符串变量未初始化

4)接口类型的对象没有用具体的类初始化

比如:List lt;会报错
    List lt = new ArrayList();则不会报错了 

  (5) 当一个对象的为空时,你没有判断为空的情况。你可以试着把下面的代码前加一行代码: 
if(str!=null && str!="") 改成: if(null!=str); if(null!=str!&&!"".equals(str)) 或者if((“”).equals(str)) 

空指针的解决办法:
重点关注报错发生的所在行,通过空指针异常产生的两条主要原因诊断具体的错误。同时为了避免空指针的发生,最好在做判断处理时将“null”或者空值放于设定的值之前

引自:https://blog.csdn.net/lyclngs/article/details/51841118







空指针的解决办法:
      
重点关注报错发生的所在行,通过空指针异常产生的两条主要原因诊断具体的错误。同时为了避免空指针的发生,最好在做判断处理时将“null”或者空值放于设定的值之前。
常见空指针异常的简要分析:
1空指针错误 Java.lang.NullPointerException
    Java中的8种基本数据类型,变量的值可以有其默认值,加入没有对其正常赋值,java虚拟机是不能
正确编译通过的,因此使用基本的Java数据类型一般不会是不会引起空指针异常的。实际开发中,大多数
的空指针异常主要与对象的操作相关。
  下面列出可能发生空指针异常的几种情况及相应解决方案:
  A:不管对象是否为空就直接开始使用。
  (JSP)代码段1
  out.println(request.getParameter("username"));
  分析:代码段1的功能十分简单,就是输出用户输入"username"的值。
      
说明:看上去,上面的语句找不出什么语法错误,而且在大多数情况下也遇不到什么问题。但是,如果某个用户在 输入数据时并没有提供表单域"username" 的值,或通过某种途径绕过表单直接输入时,此request.getParameter("username")的值为空(注意不是空字符串,是空对象 null。),out对象的println方法是无法直接对空对象操作的,因此代码段1所在的JSP页面将会抛出 "Java.lang.NullPointerException"异常。而且即使对象可能为空时,也调用Java.lang.ObjectObject对象本身的一些方法如toString()equal(Object obj)等操作。

  (JSP)代码段2
  String userName = request.getParameter("username");
  If (userName.equals("root"))
  {....}
  分析:代码段2的功能是检测用户提供的用户名,如果是用户名称为"root"的用户时,就执行一些特别的操作。                                                                                

      说明:在代码段2中,如果有用户没有提供表单域"username"的值时,字符串对象userNamenull值,不能够将一个null的对象与另一个对象直接比较,同样,代码段2所在的JSP页面就会抛(Java.lang.NullPointerException)空指针错误。

  (JSP)代码段3
  String userName = session.getAttribute
  ("session.username").toString();
        分析:代码段3的功能是将sessionsession.username的值取出,并将该值赋给字符串对象userName
      
说明:在一般情况下,如果在用户已经进行某个会话,则不会出现什么问题;但是,如果此时应用服务器重新启动 ,而用户还没有重新登录,(也可能是用户关闭浏览器,但是仍打开原来的页面。)那么,此时该session的值就会失效,同时导致session中的session.username的值为空。对一个为 null的对象的直接执行toString()操作,就会导致系统抛出(Java.lang.NullPointerException)空指针异常。

摘自https://blog.csdn.net/wuha0/article/details/7083516

该作者未说明源出处






1nullJava中的关键字,像publicstaticfinal。它是大小写敏感的,你不能将null写成NullNULL,编译器将不能识别它们然后报错。

2、就像每种原始类型都有默认值一样,如int默认值为0boolean的默认值为falsenull是任何引用类型的默认值,不严格的说是所有object类型的默认值。就像你创建了一个布尔类型的变量,它将false作为自己的默认值,Java中的任何引用变量都将null作为默认值。这对所有变量都是适用的,如成员变量、局部变量、实例变量、静态变量(但当你使用一个没有初始化的局部变量,编译器会警告你)。为了证明这个事实,你可以通过创建一个变量然后打印它的值来观察这个引用变量。

假设我们现在有一个类,例如String,对于如下代码:

String str = null;
if (str.equals("Hello World!")){
    System.out.println("Yes");
}else {
    System.out.println("No");
}123456

就会抛出空指针异常,但是,如果我们把第二行的条件判断改为:

if ("Hello World!".equals(str))1

就不会抛出空指针异常,因为Stringequals方法不是Static方法

反思

为了避免内存溢出,我们在无需类外调用的方法前,一般不加static关键字(因为静态方法会常驻内存,其生存周期与整个项目的生存周期是一致的)所以,我们应该在为变量赋初值的时候,尽量不要使用null来赋初值,如果一定是null作为初值的情况,那么在进行操作时,一定要先 Assert.isNull 一下,尽量避免对null进行操作。回到equals方法上,如果一个初值可能为空的对象实例,调用equals方法时,一定要遵循 “常量”.equals(变量) 或者 后输入的.equals(之前的)。这样就可以尽量避免空指针错误,平时多注意,养成习惯,防止日后埋下隐患。

引自:https://blog.csdn.net/tick_tock97/article/details/72824894





如何避免空NullPointerException

        为了避免NullPointerException,确保所有对象在你使用之前被初始化。注意,当你声明一个变量的引用时,你正在创建一个指向一个对象的指针。在你使用该对象的方法或域之前,你必须检验指针不为null

1. 带有字面值的字符串比较

        在应用程序代码中一种常见的情况是将字符串变量与字面值进行比较。字符串字面值可能是字符串或枚举元素。我们将通过使用字面值来调用方法,而不是通过使用null对象来调用方法。例如,观察下面的例子:

    2.检查一个方法的参数
        在执行方法之前,确保检查了参数是否为null.当参数被适当检查后,方法会继续执行。否则,你可以抛出IllegalArgumentException并且通知调用方法传入的参数有误。


3 优先使用String.valueOf()而不是toString() 
       当你的应用程序代码如要一个对象的字符串来描述时,避免使用对象的toString方法。如果你的对象的引用为nullNullPointerException将会被抛出。反之,考虑使用静态方法String.valueOf(),该方法不会抛出任何异常并且在函数参数为null的情况下会打印null


 4. 使用三元运算符
        三元运算符能帮助我们避免NullPointerException.运算符具有这样的形式:

        boolean expression ? value1 : value2;

       三元运算符能帮助我们避免NullPointerException.运算符具有这样的形式:首先,计算布尔表达式,如果表达式为true,value1被返回,否则value2被返回。我们能使用三元运算符来处理null指针,例如:

       String message = (str == null) ? "" : str.substring(0, 10);

       变量message将为空,如果str的引用为null,否则,如果str指向实际的数据,message将获取str的前10个字符。

 5.创建返回空集合而不是null的方法
       一种非常好的技术是创建一个返回空集合的方法,而不是返回null值。你的应用程序代码可以迭代空集合并使用它的方法和域,而不会抛出NullPointerException。例如:

 6.利用ApacheStringUtils
         ApacheCommons Lang是一个库,为java.lang API提供了帮助工具,例如字符串操作方法。StringUtils.java提供了字符串的操作,该类处理字符串对象为null的情况。你可以使用StringUtils.isNotEmpty, StringUtils.IsEmpty StringUtils.equals 方法,以避免NullPointerException

         7. 使用contains(), containsKey(), containsValue() 方法
         如果你的程序使用了像Maps这样的集合,考虑使用contains(), containsKey(), containsValue()方法。例如,在验证某些键存在与Map中时,返回特定键的值。

 8.检查外部方法的返回值
      实际环境中,使用外部的库很常见。这些库包含返回某个引用的方法。确保返回的引用不为null.阅读javadoc的方法,以更好理解函数功能与返回值。
      9.使用断言
      当测试代码时,断言很有用。以避免执行会抛出NullPointerException的方法。Java断言的实现通过assert关键字并抛出AssertionError.注意,你必须显式通过-ea参数启用断言。否则断言将会被忽略。

  如果你执行上述代码并传递null参数给getLength,将会出现下面的错误。

      最后,你可以使用由Junit测试框架提供的Assert类。

      

      存在NullPointerException的安全方法

      1.访问静态成员或类方法

        当你的代码试图访问静态变量或一个类的方法,即使对象的引用等于null,JVM也不会抛出NullPointerException.这是因为,在编过程中,Java编译器存储静态方法和域在特殊的位置。静态方法和域不与对象关联,而是与类名关联。

        例如下面的代码不会抛出NullPointerException.

注意,尽管SampleClass的实例为null,方法还是会被执行。当方法或域为静态时,应该以“静态”的方式来访问,即通过类名来访问。例如:SampleClass.printMessage() 



        2. instanceof 操作符
        即使对象的引用为null,instanceof操作符可使用。当引用为null时,instanceof 操作符返回false,而且不会抛出NullPointerException.例如,下面的代码:


转自:https://blog.csdn.net/Revivedsun/article/details/46581691

英文原文地址:http://examples.javacodegeeks.com/java-basics/exceptions/java-lang-nullpointerexception-how-to-handle-null-pointer-exception/?utm_source=tuicool

 

 


 

posted @ 2018-09-29 08:54  2019勇往直前  阅读(672)  评论(0编辑  收藏  举报