取消装箱Null-Object会导致NullPointerException很长,很好吗?

这段代码抛出一个NullPointerException因为它被取消Long.longValue()原始类型和Long.longValue()被调用,对吧?

如果你有一个这样的片段,这很容易看出来:

 long value = (Long) null; 

但是NullPointerException更难以进入这样一个更复杂的情况:

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

因此Java-Compiler是否有可能使这个Exception更加舒适呢? 我更喜欢IllegalArgumentException ,其中包含“你正在尝试将null-Object转换为基本类型的消息,这不可能完成!”

这不是更合适吗? 你怎么看? 这甚至可以在运行时? 我们能够确定这个演员吗? 我还没有看过java字节码。 也许它可以用在解决方案中。

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

根据Java语言规范 ,通过调用Number.longValue()Number.intValue()等进行拆箱。没有特殊的字节代码魔术发生,它与手动调用这些方法完全相同。 因此, NullPointerException是取消装箱null的自然结果(实际上是由JLS强制要求)。

抛出一个不同的exception需要在每次拆箱转换期间检查null 两次 (一次确定是否抛出特殊exception,一次隐式实际调用该方法)。 我认为语言设计师并不认为这有用。

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

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

这不是IllegalArgumentException意思。 编译器无法保证该值在运行时为null 。 它只知道类型,在你的例子中可能是String

当然,在运行时,抛出exception时,编译器知道问题是null值。 如果您使用的是调试器,则可以自己查看。 因此,从技术的角度来看 – 这是对您的问题的简短回答 – 是的,可以创建一个将错误描述中包含的编译器。 但是如果你想要一个特殊的null值消息,下一步是什么? 超出10个可接受范围之外的整数的特殊消息? 不可否认,这是一个愚蠢的例子,但我希望它是说明性的。

为这样的案例写一个小的私人助手是个好主意。 那些可以处理生成正确的强制转换,错误消息和默认值。

将操作的足够“状态”放入exception中是很好的(在这种情况下,选项名称和值 – 如果没有找到,甚至可能是选项映射的字符串表示)。

就像是:

 private long safeGetLong(Map 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."); } } 

当然,拥有允许键入访问的配置对象甚至更好。

有一些validation框架可以为您做到这一点,但我通常最终自己编写代码,因为它更适合IN8L和exception的hieracies或有关应用程序的日志记录约定。 这种通用很难做到。