这段代码会抛出一个NullPointerException
,因为它已被取消装入原始类型并调用Long.longValue()
,对吗?
如果你有这样的代码片段,那就很容易看出来了:
long value = (Long) null;
但NullPointerException
更难以处理更复杂的情况:
long propertyValue = (Long) obj.getProperty(propertyModel.getName());
因此Java-Compiler是否有可能使Exception更加舒适呢?我希望IllegalArgumentException
有一条消息,比如“你试图将一个null-Object转换成一个原始类型,这是不可能完成的!”
这不是更合适吗?你怎么看?这甚至可以在运行时?我们能够确定这个演员吗?我还没有看过java字节码。也许它可以用在一个解决方案中。
可以回答这个问题:我想知道是否有可能实现这种行为!
答案 0 :(得分:69)
根据Java language specification,取消装箱通过调用Number.longValue()
,Number.intValue()
等进行。没有特殊字节代码魔术发生,它与手动调用这些方法完全相同。因此,NullPointerException
是取消装箱null
(实际上是由JLS强制要求)的自然结果。
抛出一个不同的异常需要在每次拆箱转换期间检查null
两次(一次确定是否抛出特殊异常,并且在实际调用该方法时隐式执行)。我认为语言设计师并不认为它有用得足以保证。
答案 1 :(得分:9)
自Java 8 SE以来,还有Optional.ofNullable
long value = Optional.ofNullable(obj.getProperty(propertyModel.getName())).orElse(0L)));
答案 2 :(得分:1)
这不是IllegalArgumentException
的含义。在运行时,编译器无法保证该值为null
。它只知道类型,在你的例子中可能是String
。
当然,在运行时,抛出异常时,编译器知道问题是null
值。如果您使用的是调试器,则可以自己查看。因此,从技术的角度来看 - 这是对您的问题的简短回答 - 是的,有可能创建一个将在错误描述中包含该编译器的编译器。但是,如果您想要null
值的特殊消息,那么下一步是什么?对于超出10个可接受范围的整数的特殊消息?不可否认,这是一个愚蠢的例子,但我希望它是说明性的。
答案 3 :(得分: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和异常的hieracies或相关应用程序的日志记录约定。这种通用很难做到。