Java 如何在引发NullPointerException时查找null obejct

Java 如何在引发NullPointerException时查找null obejct,java,Java,在java中,当抛出NullPointerException时,是否有任何方法可以知道有问题对象的类的名称?当有问题的java语句中有很多可以为null的对象时,这将有助于调试代码。试图解开一些字眼: 对象永远不为空!它是一个引用,可以是null。引用有一个类型——要么是声明的变量,要么是更复杂的表达式(例如方法调用) 当您尝试取消引用null的引用时,会发生null异常,这意味着该引用不指向对象。无法获取不存在的对象的类。我想,对于那个NPE,您想检索引用null的表达式类型,是吗 唯一可以得

在java中,当抛出NullPointerException时,是否有任何方法可以知道有问题对象的类的名称?当有问题的java语句中有很多可以为null的对象时,这将有助于调试代码。

试图解开一些字眼:

对象永远不为空!它是一个引用,可以是
null
。引用有一个类型——要么是声明的变量,要么是更复杂的表达式(例如方法调用)

当您尝试取消引用
null
的引用时,会发生
null异常,这意味着该引用不指向对象。无法获取不存在的对象的类。我想,对于那个NPE,您想检索引用
null
的表达式类型,是吗


唯一可以得到(并且应该分析)的是发生NPE的源代码行。这是异常堆栈跟踪的一部分。有了这些信息,您可以调试代码。

尝试解开一些字眼:

对象永远不为空
!它是一个引用,可以是
null
。引用有一个类型——要么是声明的变量,要么是更复杂的表达式(例如方法调用)

当您尝试取消引用
null
的引用时,会发生
null异常,这意味着该引用不指向对象。无法获取不存在的对象的类。我想,对于那个NPE,您想检索引用
null
的表达式类型,是吗


唯一可以得到(并且应该分析)的是发生NPE的源代码行。这是异常堆栈跟踪的一部分。有了这些信息,您可以调试代码。

看看这些代码和注释:

public class Main {

    public static void main(final String args[])
    {
        Main test = new Main();
        test.testNull();
        System.out.println("My program still works!");  //this WILL NOT be printed asn NPE is thrown in testNull() and it's not caught - this will result in stopping the program.
    }

    private void testNull()
    {
        String aaa = null;
        aaa.charAt(1); //here you'll get a NullPointerException because there 'aaa' doesn't reference any existing object.
    }
}
输出如下所示:

Exception in thread "main" java.lang.NullPointerException  //error caught in method "main", you also have the exception class shown.
    at Main.testNull(Main.java:26)  //null was found in file Main.java in method testNull on line 26.
    at Main.main(Main.java:19)      //the method testNull was called from method main - line 19.
编辑: 你可以这样做:

public static void main(final String args[])
{
    Main test = new Main();
    try
    {
        test.testNull();
    }
    catch (final NullPointerException e) //catch the NPE
    {
        e.printStackTrace();             //print info about the cause.
        //do some other stuff to handle the exception
    }
    System.out.println("My program still works!");  //this WILL be printed
}
输出:

java.lang.NullPointerException
    at Main.testNull(Main.java:25)
    at Main.main(Main.java:13)
My program still works!

请查看此代码和注释:

public class Main {

    public static void main(final String args[])
    {
        Main test = new Main();
        test.testNull();
        System.out.println("My program still works!");  //this WILL NOT be printed asn NPE is thrown in testNull() and it's not caught - this will result in stopping the program.
    }

    private void testNull()
    {
        String aaa = null;
        aaa.charAt(1); //here you'll get a NullPointerException because there 'aaa' doesn't reference any existing object.
    }
}
输出如下所示:

Exception in thread "main" java.lang.NullPointerException  //error caught in method "main", you also have the exception class shown.
    at Main.testNull(Main.java:26)  //null was found in file Main.java in method testNull on line 26.
    at Main.main(Main.java:19)      //the method testNull was called from method main - line 19.
编辑: 你可以这样做:

public static void main(final String args[])
{
    Main test = new Main();
    try
    {
        test.testNull();
    }
    catch (final NullPointerException e) //catch the NPE
    {
        e.printStackTrace();             //print info about the cause.
        //do some other stuff to handle the exception
    }
    System.out.println("My program still works!");  //this WILL be printed
}
输出:

java.lang.NullPointerException
    at Main.testNull(Main.java:25)
    at Main.main(Main.java:13)
My program still works!
不幸的是,没有

您是指值的声明类型。它仅在编译时可用(通常向IDE报告)

编译成字节码后,声明信息被删除,因此即使是
int
也可以包含
字符串。这就是为什么方法签名如此重要

不幸的是没有

您是指值的声明类型。它仅在编译时可用(通常向IDE报告)


编译成字节码后,声明信息被删除,因此即使是
int
也可以包含
字符串。这就是为什么方法签名如此重要

在SeelenVirtuse的回答中添加:

如果您想找出导致NullPointerException的确切原因,请首先在堆栈跟踪中找到引发异常的行。这通常是跟踪中的顶行

假设是这一行:

vfoo = foo.ffoo(bar.fbar(),foo2);
这里可能的罪犯是foo或bar。vfoo无法抛出异常,因为它没有被取消引用,与foo 2相同。它不能在foo.ffoo()或bar.fbar()函数中,因为堆栈跟踪不会指向此行,但会在这些函数中显示异常。所以剩下的就是foo和bar,因为它们都被解除了引用。 因此,要找出这其中的哪一个,只需将语句分开:

temp = bar.fbar();
vfoo = foo.ffoo(temp,foo2);
现在堆栈跟踪将指向一行或另一行,您将知道bar或foo为null

您也可以在声明之前执行以下操作:

System.out.println("bar exists: "+(bar!=null));
System.out.println("foo exists: "+(foo!=null));
最后一点要谈的是:变量何时被取消引用

只有对象可以被取消引用,所以像int、float、double、char、byte之类的原语既不能为Null,也不能被取消引用。
使用时,对象将被取消引用。运算符访问对象的字段或函数(例如foo.bar()或foo.ibar=5)。此外,当您使用支持自动取消装箱的对象(例如整数、浮点、双精度、字符等)并使用任何数学或逻辑运算符(例如+、-、*、/、&、&&、&、|、|、!)时,它也会被取消引用。基本上,每次尝试访问对象的内容时,都是这样,而不仅仅是对对象的引用。

补充Seelenvirtuose的答案:

如果您想找出导致NullPointerException的确切原因,请首先在堆栈跟踪中找到引发异常的行。这通常是跟踪中的顶行

假设是这一行:

vfoo = foo.ffoo(bar.fbar(),foo2);
这里可能的罪犯是foo或bar。vfoo无法抛出异常,因为它没有被取消引用,与foo 2相同。它不能在foo.ffoo()或bar.fbar()函数中,因为堆栈跟踪不会指向此行,但会在这些函数中显示异常。所以剩下的就是foo和bar,因为它们都被解除了引用。 因此,要找出这其中的哪一个,只需将语句分开:

temp = bar.fbar();
vfoo = foo.ffoo(temp,foo2);
现在堆栈跟踪将指向一行或另一行,您将知道bar或foo为null

您也可以在声明之前执行以下操作:

System.out.println("bar exists: "+(bar!=null));
System.out.println("foo exists: "+(foo!=null));
最后一点要谈的是:变量何时被取消引用

只有对象可以被取消引用,所以像int、float、double、char、byte之类的原语既不能为Null,也不能被取消引用。 使用时,对象将被取消引用。运算符访问对象的字段或函数(例如foo.bar()或foo.ibar=5)。此外,当您使用支持自动取消装箱的对象(例如整数、浮点、双精度、字符等)并使用任何数学或逻辑运算符(例如+、-、*、/、&、&&、&、|、|、!)时,它也会被取消引用。基本上每次你尝试交流时都是这样