为什么空数组引用的数组访问表达式不会抛出 NullPointerException?

2023-12-25

考虑以下代码:

int[] r = null;
r[0] = 1 % 0;

我本以为这会引发NullPointerException: 根据JLS 第 15.7.1 节 https://docs.oracle.com/javase/specs/jls/se8/html/jls-15.html#jls-15.7.1:

二元运算符的左侧操作数似乎在右侧操作数的任何部分被求值之前被完全求值。

=是一个二元运算符(如JLS 第 15.2 节 https://docs.oracle.com/javase/specs/jls/se8/html/jls-15.html#jls-15.2- JLS Sec 15.26 描述了赋值运算符),并且完全评估左侧操作数将导致NullPointerException。然而,一个ArithmeticException抛出,表示在完全评估左侧操作数之前评估右侧操作数。

Why?


规格简单的赋值运算符 https://docs.oracle.com/javase/specs/jls/se8/html/jls-15.html#jls-15.26.1描述了这种行为:

...

如果左侧操作数是数组访问表达式(第 15.10.3 节),可能用一对或多对括号括起来,则:

  • 首先,计算左侧操作数数组访问表达式的数组引用子表达式。如果此计算突然完成,则出于同样的原因,赋值表达式也会突然完成;索引子表达式(左侧操作数数组访问表达式的)和右侧操作数不会被求值,也不会发生赋值。

这样就正常完成了。

  • 否则,将计算左侧操作数数组访问表达式的索引子表达式。如果此计算突然完成,则赋值表达式也会出于同样的原因突然完成,并且不会计算右侧操作数并且不会发生赋值。

这样就正常完成了。

  • 否则,将计算右侧操作数。如果此计算突然完成,则赋值表达式也会出于同样的原因突然完成,并且不会发生赋值。

这突然完成,与ArithmeticException.

  • 否则,如果数组引用子表达式的值为 null,则不会发生赋值并引发 NullPointerException。

这永远不会被执行。

因此,第 15.7.1 节的引用似乎存在不一致之处,或者至少过于简单化。


有趣的是,对于复合赋值运算符,没有观察到相同的行为,例如

int[] arr = null;
arr[0] += 1 % 0;

does产量aNullPointerException.

JLS 第 15.26.2 节 https://docs.oracle.com/javase/specs/jls/se8/html/jls-15.html#jls-15.26.2描述了这一点。不过,这也许并不令人惊讶,因为:

形式的复合赋值表达式E1 op= E2相当于E1 = (T) ((E1) op (E2)), where T是类型E1, 除了那个E1仅评估一次。

换句话说,这段代码(大致)相当于:

arr[0] = arr[0] + 1 % 0;

so the NullPointerException发生在评估右手简单赋值的操作数。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

为什么空数组引用的数组访问表达式不会抛出 NullPointerException? 的相关文章

  • Maven 2:如何将当前项目版本打包在WAR文件中?

    我正在使用 Maven 2 构建我的 Java 项目 并且正在寻找一种向用户呈现 pom xml 当前版本号的方法 例如使用 Servlet 或 JSP 据我所知 最好的方法是 Maven 将版本号作为文本文件打包到 WAR 中 这使我能够
  • 具有默认值的 Java JAX-RS 自定义参数

    假设我有这个 这只是一个示例 GET Path value address Produces application json public Response getAddress QueryParam user User user 用户是
  • 将 Hibernate 对象序列化为 JSON 时抛出异常

    好吧 我正在使用 Hibernate 将一个小型数据库加载到一些表示表的类并与数据库交互 一切都很好 我真的可以看到所有结果 而且我没有任何空字段 所有这些都已被使用 这里我展示了 主 类 表 import javax persistenc
  • 手动编辑 Jar 以更改包名称

    我有一个来自外部源的 jar 文件 jar 中的所有类都位于 com xyz 包中 我想将所有类移动到 com xyzold 包中 这是否像解压缩 jar 将 xzy 文件夹重命名为 xyzold 并重新压缩它一样简单 或者我还需要修改每个
  • 使用 ChannelExec 的命令未执行 - Jsch

    我正在使用 Jsch 在服务器中创建一个文件并执行一些命令 对于文件创建 它工作正常 但是对于命令执行 则不然 它保持状态 1 仍在处理它 并永远保持该状态 这种情况发生在 shell 执行或我尝试成为 root 时 请按照以下方法操作 p
  • Java 正则表达式 - 字母数字,最多一个连字符,句点或下划线,七个字符长

    我是 Java 正则表达式工具的新手 尽管它们潜力巨大 但我很难完成这项任务 我想编写一个正则表达式来验证遵循以下语法的输入字符串 小写字母和数字的任意组合 仅一个下划线 一个破折号或一个句号 无其他特殊字符 最小长度为 5 我想出了以下解
  • 如何拦截 REST 端点以接收所有标头?

    我当前的代码是 Path login RequestScoped public class LoginResource GET SecurityChecked public Response getUser HeaderParam AUTH
  • 定期更新 SWT 会导致 GUI 冻结

    Problem 当 GUI 字段定期更新时 SWT 会冻结 我想要一个基于 SWT 的 GUI 其中文本字段的值会定期递增 最初我从单独的线程访问 textField 导致抛出异常 线程 Thread 0 org eclipse swt S
  • Intellij 中的 Google OR-Tools:UnsatisfiedLinkError

    我正在建立一个应该使用 Google OR Tools 的 java 框架 下面的代码编译成功 但在运行时抛出异常 Exception in thread main java lang UnsatisfiedLinkError com go
  • 我想在java中使用XQuery进行Xml处理

    我想用XQuery用于从 java 中的 Xml 获取数据 但我没有得到需要为此添加哪个 Jar 我在谷歌上搜索了很多 但没有得到任何有用的例子 例如我得到以下链接 https docs oracle com database 121 AD
  • 在 Java 中将弯音发送到 MIDI 音序器

    我了解启动和运行 MIDI 音序器的基础知识 并且希望能够在播放过程中增加 减小序列的音高 但弯音是发送到合成器而不是音序器的消息 我尝试将音序器的接收器设置为合成器的发射器 当我发送弯音短消息时 音序器保持相同的音调 但随后合成器以新的弯
  • 如何在Java媒体框架中学习.wav持续时间?

    我正在尝试使用 java 媒体框架将 mov 文件与 wav 文件合并 因此我需要知道它们的持续时间 我怎样才能做到这一点 任何想法 将不胜感激 您可以使用以下方式了解声音文件的持续时间 即 VitalyVal 的第二种方式 import
  • Hibernate HQL:将对值作为 IN 子句中的参数传递

    我面临一个问题 如何使用 IN 子句将查询中的成对值的参数传递给 HQL 例如 select id name from ABC where id reg date in x y 并且参数是不同的数据类型string id 和reg date
  • 了解 Spark 中的 DAG

    问题是我有以下 DAG 我认为当需要洗牌时 火花将工作划分为不同的阶段 考虑阶段 0 和阶段 1 有些操作不需要洗牌 那么为什么 Spark 将它们分成不同的阶段呢 我认为跨分区的实际数据移动应该发生在第 2 阶段 因为这里我们需要cogr
  • 使用 secp256r1 曲线和 SHA256 算法生成 ECDSA 签名 - BouncyCastle

    我正在尝试使用带有 secp256r1 曲线 P256 的 ECDSA 和用于消息哈希的 SHA256 算法生成签名 我也在使用 Bouncy Castle 库 下面的代码 public class MyTest param args pu
  • 警告:无法更改每个人的权限:

    当运行 Java 快速入门示例时https developers google com drive web quickstart java hl hu https developers google com drive web quicks
  • 如何用表达式语言获取布尔属性?

    如果我有一堂这样的课 class Person private int age public int getAge return age public boolean isAdult return age gt 19 我可以得到age像这样
  • 春季 CORS。在允许的来源中添加模式

    查看CORS的弹簧指南 以下代码启用所有允许的来源 public class MyWebMVCConfigurer extends WebMvcConfigurerAdapter Override public void addCorsMa
  • 每次我们调用浏览器时,在 selenium 中使用 driver.manage().window().maximize() 是否好?

    We use driver manage window maximize 最大化浏览器 我在网上看到一些使用的例子driver manage window maximize 尽管不需要最大化浏览器 例如 gmail 登录 我还看到使用 se
  • 如何在不同版本的Google App Engine中使用自定义域名?

    我使用谷歌应用程序引擎作为我的 Android 和 Web 应用程序的服务器 我使用 Android Studio 开发了 Android 应用程序 并使用 Eclipse 开发了 Web 应用程序 我在应用程序引擎中部署了两个版本 第一个

随机推荐