当抛出NullPointerException时,java中是否有任何方法可以知道违规对象的Class的名称?当有问题的java语句有很多可以为null的对象时,这将有助于调试代码。
答案 0 :(得分:3)
看看这段代码和评论:
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!
答案 1 :(得分:1)
试图解开你的一些措辞:
对象永远不会是null
!它是一个可以null
的引用。引用有一个类型 - 要么是声明的变量,要么是更复杂的表达式(例如方法调用)。
当您尝试取消引用NullPointerException
的引用时会发生null
,这仅表示引用指向对象。没有机会获取不存在的对象的类。我想,你想在NPE的情况下检索引用null
的表达式的类型,不是吗?
唯一可以获得(并且应该分析)的是NPE发生的源代码行。这是异常堆栈跟踪的一部分。有了这些信息,您就可以调试代码。
答案 2 :(得分:0)
不幸的是没有。
您的意思是声明类型的值。它仅在Compile-Time(通常向IDE报告)中提供。
编译成字节码后,声明信息被删除,因此即使int
也可以包含String
。这就是方法签名非常重要的原因!
答案 3 :(得分:0)
添加到Seelenvirtuose的答案:
如果要查明导致NullPointerException的确切原因,请首先在堆栈跟踪中找到引发异常的行。这通常是追踪中的顶线。
让我们说这就是这条线:
vfoo = foo.ffoo(bar.fbar(),foo2);
这里可能的罪犯是foo或bar。 vfoo不能抛出异常,因为它没有被解除引用,与foo 2相同。它不能在函数foo.ffoo()或bar.fbar()中,因为那时堆栈跟踪不会#39 ; t指向此行,但会在这些函数中显示异常。因此,剩下的一切都是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等原语既不能为空也不能被解除引用。 使用时,对象被取消引用。运算符访问对象的字段或函数(例如foo.bar()或foo.ibar = 5)。当你使用支持自动装箱的对象(例如Integer,Float,Double,Char,...)并使用任何数学或逻辑运算符(例如+, - ,*,/,&,&)时,它也会被取消引用。 &,|,||,!)。它基本上是每次您尝试访问对象的内容而不仅仅是对它的引用。