将 Null-Object 拆箱为原始类型会导致 NullPointerException,可以吗?

问题描述 投票:0回答:4

这个片段会抛出一个

NullPointerException
,因为它被拆箱为原始类型并且
Long.longValue()
被调用,对吧?

如果您有这样的片段,那就更容易看出:

long value = (Long) null;

但是

NullPointerException
在这样更复杂的情况下就更难了:

long propertyValue = (Long) obj.getProperty(propertyModel.getName());

那么 Java 编译器是否有可能从中产生更舒适的异常?我更喜欢带有类似消息的

IllegalArgumentException
“您正在尝试将 null 对象转换为原始类型,这是无法完成的!”

这样不是更合适吗?你怎么认为?这在运行时是否可能?我们能确定这个演员阵容吗?我还没看过java字节码。也许它可以用于解决方案。

这个问题可以回答:我想知道是否有可能实现这种行为!

java nullpointerexception
4个回答
105
投票

根据 Java 语言规范,拆箱是通过调用

Number.longValue()
Number.intValue()
等进行的。没有发生特殊的字节码魔法,与手动调用这些方法完全相同。因此,
NullPointerException
是拆箱
null
的自然结果(实际上是 JLS 强制要求的)。

抛出不同的异常需要在每次拆箱转换期间检查

null
两次(一次确定是否抛出特殊异常,一次在实际调用方法时隐式检查)。我想语言设计者认为它没有足够的用处来保证这一点。


26
投票

从 Java 8 SE 开始,还有Optional.ofNullable

long value = Optional.ofNullable(obj.getProperty(propertyModel.getName())).orElse(0L);

1
投票

这不是

IllegalArgumentException
的意思。编译器无法保证该值在运行时之前都是
null
。它只知道类型,在您的示例中可能是
String

当然在运行时,当抛出异常时,编译器知道问题出在

null
值上。如果您使用调试器,您可以自己看到这一点。因此,从技术角度来看 - 这是对您问题的简短回答 - 是的,有可能创建一个编译器,将其包含在错误描述中。但如果您想要
null
值的特殊消息,接下来该怎么办?针对超出某个可接受范围超过 10 的整数的特殊消息?诚然,这是一个愚蠢的例子,但我希望它能说明问题。


1
投票

针对此类情况编写一个小型私人助手是个好主意。这些可以处理生成正确的转换、错误消息和默认值。

最好将足够的操作“状态”放入异常中(在本例中是选项名称和值 - 如果未找到,甚至可能是选项映射的字符串表示形式)。

类似:

private long safeGetLong(Map<String, Option> options, String name) {
  if (name == null || options == null)
    throw new IllegalArgumentExcption("You need to give options and name. (name="+name+", opts=" + options));
  Object val = options.get(name);
  if (val == null)
    throw new ConfigurationException("The option name="+name+" is unknown");
  if (val instanceof Long)
    return val.longValue();

  String strVal = null;
  try
  {
    strVal = val.toString();
    return Long.parseValue(strVal);
  } catch (Exception ex) {
    throw new ConfigurationException("Cannot parse " + name + "=" + strVal + " into a Long.");
  }
}

当然,拥有一个允许类型化访问的配置对象就更好了。

有一些验证框架可以为您做到这一点,但我通常最终自己编写代码,因为它更适合 IN8L 和异常层次结构或相关应用程序的日志约定。很难使其通用。

© www.soinside.com 2019 - 2024. All rights reserved.