NullPointerException 是什么?如何修复它?

共12个回答,已解决, 标签: java nullpointerexception

空指针异常是什么 (Java.lang.NullPointerException) 是什么原因导致的?

可以使用哪些方法/工具来确定原因,以便阻止异常导致程序过早终止?

第1个答案(采用)

声明引用变量 (即对象) 时,实际上是在创建指向对象的指针。请考虑以下代码,其中声明了原始类型的变量Int:

Int x;
X = 10;

在这个例子中,变量X是一个IntJava 将把它初始化为0给你的当你分配它的值时10第二行,你的价值10写入所引用的内存位置X.

但是,当您尝试声明引用时类型不同的事情发生了取以下代码:

整数 num;
Num = 新整数 (10);

第一行声明了一个名为Num,但是它实际上还不包含原始值。相反,它包含一个指针 (因为类型是整数这是一个引用类型)。因为你还没有说要指向什么,所以 Java 将它设置为Null意思是"我指的是没什么”。

在第二行,新的关键字用于实例化 (或创建) 类型的对象整数和指针变量Num被分配到那个整数对象。

NullPointerException声明变量但未创建对象时发生。所以你指的是不存在的东西。

如果您试图取消引用Num在创建对象之前,您会得到NullPointerException。在最琐碎的情况下,编译器会抓住问题,让你知道可能没有初始化 num,”但是有时您可能会编写不直接创建对象的代码。

例如,您可能有如下方法:

调用父类做点什么 (SomeObject obj) {
//对 obj 做点什么
}

在这种情况下,您没有创建对象Obj,而是假设它是在做某事调用了方法。注意,可以像这样调用方法:

做点什么 (无效);

在这种情况下ObjNull。如果该方法旨在对传入对象执行某些操作,则抛出NullPointerException因为这是一个程序员错误,程序员需要这些信息来进行调试。

或者,在某些情况下,该方法的目的不仅仅是对传入的对象进行操作,因此可以接受 null 参数。在这种情况下,你需要检查空参数和行为不同。您还应该在文档中解释这一点。例如,做某事可以写成:

/* *
* @ Param obj 任选富于 ____。在这种情况下,可能为 null
结果将会是…
*/
调用父类做点什么 (SomeObject obj) {
如果 (obj!= null) {
做点什么
} 其他 {
做点别的
}
}

最后,如何使用堆栈跟踪来确定异常和原因

编辑从 @ Perimosh

我想添加一些东西,但是不能评论,所以我在这里添加它。你从来没有抓到过 NullPointerException!这是一个可怕的做法。如果你这样做,这意味着很可能你的代码中有一个错误。

第2个答案

NullPointerExceptionS 是当您尝试使用指向内存中没有位置 (null) 的引用时出现的异常,就好像它引用了一个对象一样。对空引用调用方法或尝试访问空引用的字段将触发NullPointerException。这些是最常见的,但是在NullPointerExceptionJavadoc 页。

可能是我能想出的最快的示例代码来说明NullPointerException将是:

公共类示例 {

公共静态 void main (字符串 [] args) {
对象 obj = null;
Obj.hashCode ();
}

}

在里面的第一行主要的,我明确设置了对象参考Obj等于Null。这意味着我有一个引用,但是它没有指向任何对象。之后,我试图通过调用对象上的方法来将引用视为指向对象。这导致了NullPointerException因为在引用指向的位置没有要执行的代码。

(这是一个技术问题,但我认为值得一提的是: 指向 null 的引用与指向无效内存位置的 C 指针不同。空指针实际上没有指向任何地方,这与指向碰巧无效的位置有微妙的不同。))

第3个答案

什么是 NullPointerException?

一个好的开始是JavaDocs。他们涵盖了这一点:

当应用程序试图在以下情况下使用 null 时引发 对象是必需的。这些包括:

  • 调用 null 对象的实例方法。
  • 访问或修改空对象的字段。
  • 将 null 的长度视为数组。
  • 像数组一样访问或修改 null 的插槽。
  • 抛出 null,就好像它是一个可抛出的值一样。

应用程序应该抛出这个类的实例来指示其他 Null 对象的非法使用。

如果您尝试使用空引用,也会出现这种情况同步也会抛出这个异常根据 JLS:

同步声明:
同步 (表达式) 块
  • 否则,如果表达式的值为 null,则NullPointerException被扔了

我该如何修复它?

所以你有一个NullPointerException。你怎么修的?让我们举一个简单的例子NullPointerException:

公共类打印机 {
私有字符串名称;

公共 void setName (字符串名称) {
名称 = 名称;
}

公共空白打印 () {
打印字符串 (名称);
}

私有 printprint String (字符串 s) {
系统。输出。 println (“s.长度 ()”);
}

公共静态 void main (字符串 [] args) {
打印机打印机 = 新打印机 ();
打印机.print ();
}
}

标识 null 值

第一步是准确识别导致异常的值有哪些。为此,我们需要做一些调试。学习阅读 a 是很重要的Stacktrace。这将向您显示引发异常的位置:

线程 “main” java.lang.NullPointerException 中的异常
在打印机。打印字符串 (打印机 java
在打印机。打印 (打印机。 java: 9)
在打印机。主 (打印机。 java: 19)

在这里,我们看到在 13 号线 (在打印字符串方法)。查看行并检查哪些值是空的 添加日志记录语句或使用调试器。我们发现S为 null,并调用长度方法引发异常。我们可以看到,当程序停止抛出异常时,美国长度 ()从方法中删除。

跟踪这些值来自哪里

接下来检查这个值来自哪里。通过跟踪方法的调用方,我们可以看到S是通过与打印字符串 (名称)打印 ()方法,和这个名字为 null。

应该设置这些值的跟踪

在哪里这个名字定了?在SetName (字符串)方法。有了更多的调试,我们可以看到这个方法根本没有被调用。如果调用了该方法,请确保检查订单调用这些方法,而不调用 set 方法之后打印方法。

这足以给我们一个解决方案:打印机.setName ()在打电话之前打印机.print ().

其他修复

变量可以有一个默认值(和SetName可以防止它被设置为 null):

私有字符串名称 = "";

要么是打印或者打印字符串方法可以检查 null,例如:

打印字符串 (
第4个答案

问题: 是什么导致了NullPointerException(NPE)?

正如你应该知道的,Java 类型分为原始类型 (布尔, Int等) 和引用类型。Java 中的引用类型允许您使用特殊值Null这是说 “没有对象” 的 Java 方式。

ANullPointerException每当您的程序尝试使用Null好像是真正的参考。例如,如果你这样写:

公共类测试 {
公共静态 void main (字符串 [] args) {
字符串 foo = null;
长度 ();/这里
}
}

标有 “这里” 的语句将尝试运行长度 ()A 上的方法Null参考,这将抛出一个NullPointerException.

你可以使用多种方式Null将导致 a 的值NullPointerException。事实上,你唯一的东西可以用 a 做Null在不引起 NPE 的情况下:

  • 将其分配给引用变量或从引用变量中读取它,
  • 将其分配给数组元素或从数组元素中读取它 (前提是数组引用本身不为空!),
  • 将其作为参数传递或返回,或者
  • 使用测试它= =或者!=运营商,或者替代 instanceof.

问题: 如何阅读 NPE 堆栈跟踪?

假设我编译并运行上面的程序:

$ Java c 测试.java
Java 测试
线程 “main” java.lang.NullPointerException 中的异常
在 Test.main (测试.java: 4)
$

第一次观察: 编译成功!程序中的问题不是编译错误。这是一个运行时错误。(一些 ide 可能会警告你的程序总是会抛出异常.但是标准Javac编译器没有。)

第二个观察: 当我运行程序时,它会输出两行 “gobbledy-gook”。错了!!这不是废话。这是一个 stacktrace.它提供了重要信息如果你花时间仔细阅读,这将有助于你追踪代码中的错误。

所以让我们看看它是怎么说的:

线程 “main” java.lang.NullPointerException 中的异常

堆栈跟踪的第一行告诉你一些事情:

  • 它告诉你抛出异常的 Java 线程的名称。对于一个只有一个线程的简单程序 (比如这个线程),它将是 “main”。让我们继续前进.
  • 它会告诉你抛出的异常的全名; 即Java.lang.NullPointerException.
  • 如果异常具有相关联的错误消息,则该错误消息将在异常名称后输出。NullPointerException在这方面是不寻常的,因为它很少有错误信息。

第二行是诊断 NPE 最重要的一行。

在 Test.main (测试.java: 4)

这告诉我们很多事情:

  • “在测试中。 main” 说我们在主要的的方法测试上课。
  • “Test.java: 4” 给出了类的源文件名,它告诉我们发生这种情况的语句在文件的第四行。

如果你计算上面文件中的行,第四行是我用 “这里” 注释标记的行。

请注意,在一个更复杂的例子中,NPE 堆栈跟踪中会有很多行。但是你可以确定第二行 (第一个 “at” 行) 会告诉你 NPE 被扔在哪里 1.

简而言之,堆栈跟踪将明确地告诉我们程序的哪个语句抛出了 NPE。

1-不太对。有些东西叫做嵌套异常.

第5个答案

就像你试图访问一个对象Null。考虑下面的例子:

ObjA 型;

在这个时候,你刚刚宣布这个对象初始化或实例化。当你试图访问其中的任何属性或方法时,它会抛出NullPointerException这是有道理的。

请参见下面的示例:

字符串 a = null;
将抛出 System.out.println (a.toString ());//NullPointerException
第6个答案

当应用程序试图在需要对象的情况下使用 null 时,会引发 null 指针异常。这些包括:

  1. 调用的实例方法Null对象。
  2. 访问或修改的视野Null对象。
  3. 取的长度Null好像是一个数组。
  4. 访问或修改的插槽Null好像是一个数组。
  5. 投掷Null就好像它是一个可投掷的值。

应用程序应该抛出该类的实例来指示Null对象。

参考:Http://docs.oracle.com/javase/8/docs/api/java/lang/NullPointerException.html

第7个答案

ANullPointer 是一个指向任何地方的指针。解引用指针时P,你说 “把存储在“ p ”中的位置的数据给我。当P是一个Null指针,存储在P无处可去,你是说 “现在把位置的数据给我”。显然,它不能这样做,所以它会抛出一个空指针异常.

一般来说,这是因为一些东西没有被正确初始化。

第8个答案

已经有很多解释来解释它是如何发生的以及如何修复它,但是你也应该遵循最佳实践要避免NullPointerException一点都没有

另见: 最佳实践的好列表

我想补充一点,非常重要的是,充分利用决赛修饰语。 在 Java 中使用 “最终” 修饰符

总结:

  1. 使用的决赛实现良好初始化的修饰符。
  2. 避免在方法中返回 null,例如在适用时返回空集合。
  3. 使用注释@ NotNull@ 可空
  4. 快速失败,当 null 对象不应该为 null 时,使用断言来避免 null 对象在整个应用程序中传播。
  5. 首先对已知对象使用 equals:如果 (“知道对象”。等于 (不知道对象)
  6. 更喜欢价值 ()通过 toString ()。
  7. 使用空保险箱StringUtils方法StringUtils。isEmpty (空).
第9个答案

空指针异常是指在不初始化对象的情况下使用对象的指示器。

例如,下面是一个学生班,它将在我们的代码中使用它。

公开课学生 {

私有 int id;

公共 int getId () {
返回这个 id;
}

公共 setId (int newId) {
这个 id = newId;
}
}

下面的代码给你一个空指针异常。

公立学校

学生学生;

公立学校 () {
试试 {
学生.getId ();
}
捕获 (异常 e) {
System.out.println (“空指针异常”);
}
}
}

因为你用的是学生,但是你忘了像 如下所示的正确代码:

公立学校

学生学生;

公立学校 () {
试试 {
学生 = 新学生 ();
学生.setId (12);
学生.getId ();
}
捕获 (异常 e) {
System.out.println (“空指针异常”);
}
}
}
第10个答案

在 Java 中,所有东西 (不包括基本类型) 都是以类的形式存在的。

如果你想使用任何对象,那么你有两个阶段:

  1. 申报
  2. 初始化

示例:

  • 声明:对象对象;
  • 初始化:对象 = 新对象 ();

数组概念也一样:

  • 声明:项目 [] = 新项目 [5];
  • 初始化:项目 [0] = 新项目 ();

如果没有给出初始化部分,则NullPointerException出现。

第11个答案

Java您声明的所有变量实际上都是对对象 (或基本体) 的 “引用”,而不是对象本身。

当您尝试执行一个对象方法时,引用会要求活对象执行该方法。但是,如果引用引用 NULL (无、零、无效、 nada),则该方法无法执行。然后运行时通过抛出一个 NullPointerException 来让你知道这一点。

你的引用是 “指向” null,因此是 “Null-> Pointer”。

对象存在于虚拟机内存空间中,访问它的唯一方法是使用这个参考资料。举这个例子:

公共类一些 {
私有 int id;
公共 int getId () {
返回这个 id;
}
公共 setId (int newId) {
这个 id = newId;
}
}

在代码的另一个地方:

指向类型为 Some () 的新对象;//
一些其他的引用 = null;/

//执行 setId 方法,现在私有 var id 为 1

System.out.println (参考.getId ());//将 1 打印到控制台

现在它们都指向了唯一的对象。

引用 = null;//“引用” 现在指向 null。

但是 “其他引用” 仍然指向 “真实” 对象,所以这个 print 1 也是.
系统输出打印输出 (其他参考 getId ());

猜会发生什么
System.out.println (引用.getId ());//: 因为 “引用” 指向 NULL remember,所以 S 抛出 NullPointerException.

这是一件重要的事情 -- 当没有更多的对象引用时 (在上面的例子中,当参考其他参考两者都指向 null),则对象是 “不可访问的”。我们无法使用它,所以这个对象已经准备好被垃圾收集,在某个时候,虚拟机将释放这个对象使用的内存,并分配另一个内存。

第12个答案

A 的另一次出现NullPointerException当声明对象数组时发生,然后立即尝试取消引用其中的元素。

【】短语 = 【 10 】新串;
串关键词 = "鸟";
用于 (字符串短语: 短语) {
系统。输出。 println (短语。等于 (关键短语));
}

如果比较顺序相反,可以避免这种特殊的 NPE; 即使用。平等在保证的非空对象上。

数组内部的所有元素初始化为它们的公共初始值; 对于任何类型的对象数组,这意味着所有元素都是Null.

必须初始化数组中的元素之前访问或取消引用它们。

字符串 [] 短语 = 新字符串 [] {“鸟” 、 “我的鸟” 、 “鸟”};
串关键词 = "鸟";
用于 (字符串短语: 短语) {
系统。输出。 println (短语。等于 (关键短语));
}

相关问题

Java 是 "逐项传递" 还是 "按值传递"? 如何比较 Java 中的字符串? 什么是 Null Pointerexception, 我如何修复它? NullPointerException 是什么?如何修复它? 在 android 的 Toast 消息中打印 StringArray [] 时 NullPointerException