我有我的 Java 程序,我得到一个 NullPointerException,我看到了其他问题,但它们来自其他程序的人,它不适用于我的程序,我想把我的程序的 2000 行留在这里,以便你可以解决我的问题,但人们不让。
看,我的程序是这样的
Object a = null;
// 500 líneas de código
// Dentro de un bucle, dentro de un if, dentro de un for...
a = algunaFuncionDeMilLineasQueNoTeVoyAMostrar(
parámetrosDeLosQueNoTeDiréElValor)
// Cerrando for, cerrando if, cerrando bucle.
// Otras 500 líneas de código
// Una de estas líneas lanza el NPE, pero no te diré cuál.
a.toString();
z.hazAlgunaCosa();
x.haxY().hazM().cuantoFaltaParaLasVacaciones().andaMiraUnPatoQuePasaPorAhi();
这是错的?如果 NullPointerExceptions (NPEs) 经常发生,为什么没有万能的解决方案呢?
解决方案是(鼓)...
不要使用空变量或表达式的方法或属性
如果你有一条线:
并给你一个 NPE,当你执行
p
它时它是值得的null
。在执行该行之前,请确保它具有非空值。就这些...
即使程序不同,也无需重复同一个问题一百万次。很清楚,不是吗?正如所承诺的,永远永远解决。
如果您的线路类似于
完全相同,如果任何方法返回null,当尝试调用其对应方法时,JVM 将抛出 NullPointerException。与前一个示例的唯一区别是 JVM 只会在该行显示一个错误,并且您必须找出null出现在哪一步。
自该语言的第 14 版以来,这已经发生了一些变化,它引入了一个选项来告诉 JVM 向我们提供有关引发异常1的代码的更详细的消息。此选项默认禁用,因此要启用它,需要
-XX:+ShowCodeDetailsInExceptionMessages
在执行程序时包含 JVM 命令行参数。现在是当有人抗议时:“但这对我的问题没有帮助,我在我的程序中得到一个 NullPointerException 我在这里写2 ”?
答案:如果有 NullPointerException,你的问题不是 NullPointerException。
程序员有责任了解他们的程序是如何工作的以及数据是如何组织的。这不是可以下载到 StackOverflow 的问题。如果您有 NPE,则您处于以下一种(或多种)情况:
典型的情况是说“在这种方法中它
a
可以是1或2”并且做你的问题是它
a
值得你没想到的东西,再加上你没有进行防御性编程并且没有控制值的事实。调试您的程序以修复 的值a
,添加一个default
在值意外时引发异常的程序。您有一个如此复杂的方法,以至于您不知道何时将值分配给引用。修改您的程序,使其易于阅读和理解。不要像那些说“写作很容易,我们希望有一天能学会阅读”的老埃尔波尼亚人那样做。如果您想检查您的程序是否按预期工作,请使用调试工具或生成日志消息,以便您可以验证其操作。如果您需要互联网上的人来解释您的程序是如何工作的,请考虑另一种职业。
您的 API 有问题。您已经按照上面提到的所有步骤进行了操作,最后您发现起源的原因是您正在调用
java.util.Collections.toArray()
它并且它返回了一个 valuenull
。检查方法的文档,检查你传递的参数等。如果您仍然找不到解决方案,恭喜!!!!现在您有一个对 SO 有效的问题(“为什么 java.util.Collections.toArray() 返回 null 给我?”)您有一个以某种方式初始化的向量,但您从未在内部对其进行初始化。这样做
tipo1 vector[] = new tipo1[n];
并不意味着向量将神奇地填充type1的对象。您必须为向量的每个位置执行 New type1。关于数组的另一个注意事项
由于这是一个经常出现的混淆,我们将坚持最后一点:
创建对象数组时,会创建数组但不会创建对象。在上面的第一行代码之后,您有对象myArray(您可以执行myArray.length),但该对象仅包含 10 个对null的引用( myArray[0],myArray[1] ...);他们指向的实例尚未分配。如果没有为这些引用分配实例,则尝试调用方法或属性将引发 NullPointerException。
1有关更多信息,请参阅JEP 358:有用的 NullPointerExceptions。
2后面是一千行代码,当然也没有说明NPE是在哪一行启动的。
如果你怀疑变量有
null
y 会报错,NullPointerException
通过添加try-catch块来解决它,它会恢复错误。你可以给你的对象 a ,它会将作为字符串new Object
上传到你的应用程序,这样你就可以看到哪个对象破坏了你的程序流。null
您还可以阅读代码中的警告,它们有很大帮助。
下午好,当然有处理 NPE 的解决方案,不一定是处理异常,我建议您使用Null Object Pattern设计模式,这将使您的代码更健壮,您将拥有控制权它类型的错误,从而防止程序在运行时被中断。
这是UML图:
实现非常简单。我建议您不要验证 object.something.something != null 并且不要滥用泛化的 try/catch,因为这不会解决您的问题,他们只会控制它,但潜在的问题将继续存在。
干杯!!!
您的部分问题可能是您
funciondeMilLineas
正在执行非常长且非常复杂的函数,其中很容易出错。一个函数应该有多长的一个简单的经验法则是它可以在屏幕上查看。在我的显示器上大约有 40 行。您可以使用字母的大小,但或多或少是长度。学习将代码分解为函数并不容易。我读过的关于我最喜欢的主题的内容是在Robert C. Martin的一本名为Clean Code的书中,其中有一整章是关于函数的。它说的是:
显然,理解这意味着什么并在实践中应用它有点困难。但我认为值得学习的是,在制作有效但过于复杂而无法扩展的程序之前。
问题
NullPointerException
是您还没有初始化任何 Java 引用。把它简化为野兽是你在new
某处遗漏了一些东西。PS:如果真的搞到一千行的函数,不要怀疑是错的。那必须分开。
如果我可以贡献一些东西,我不这么认为,因为他们在上面的反应很好(现在我将投票),我会补充:
- 如果它是一个参数,你应该在使用它之前检查它。- 如果是结果,请使用可选项
例子:
您可以实现 a
try{}catch(NullPointerException){}
因为,正如它所说,它捕获所有为空的字段,或者在调用它们时确保它们不为空。您可以实现一个接收对象的方法并检查它是否不为空或者更好地确保在编程时它已经包含引用或已初始化。
有一个选项似乎没有太多用于缓解 NullPointerExceptions 问题,那就是
java.util.Objects
. 这个类,自 Java 7 起就出现在 JDK 中,包含几个静态方法,可以帮助处理空值。最基本的就是简单地测试一个变量是否为空。通常这样做:
必须使用 == 总是让我有点困扰,因为它通常不是比较对象的正确方法(尽管在这种情况下它可以按预期工作)。使用对象类我们可以做到:
如果我们也静态导入对象:
它更加清晰、简洁和优雅。此外,在 Streams 中使用它甚至更好,例如在过滤器中:
我从 Objects 类中发现的另一种很酷的方法是 requireNonNullElse() (尽管此方法仅在 Java 9 之后才存在)。通常,如果我们想分配一个变量来验证它不为空,我们会这样做:
(我们也可以在这里使用三元运算符,但类似)。使用对象,我们可以这样做:
还有另一个类似的版本接受供应商作为第二个参数:
两者有什么区别?Java 的工作方式, requireNonNullElse() 将评估第二个参数,即使第一个参数不是 null 并且不需要返回它。因此,如果第二个参数很难创建,占用大量内存或大量处理,您可以使用 requireNonNullElseGet() 并在供应商的主体中构建对象。由于 lambda 表达式的结果在实际需要之前不会被评估,我们可以避免创建一些不会被使用的东西。
Objects 类中还有一些其他方法可以帮助防止 NullPointerExceptions,但在我看来,这些方法是最重要的。您可以在此处查看文档: https ://docs.oracle.com/en/java/javase/14/docs/api/java.base/java/util/Objects.html
它很容易解决,验证。NullPointerExceptions 据说是程序员错误产生的,如果你知道一个方法可以返回一个对象或者需要对一个对象起作用,就放一个: