2010-03-04 36 views
24

这段代码会抛出一个NullPointerException,因为它将其拆箱为原始类型,并调用Long.longValue(),对吧?取消装箱Null对象长时间导致NullPointerException,罚款?

那甚至很容易看到,如果你有这样一个片段:

long value = (Long) null; 

NullPointerException更难更复杂的情况是这样得到:

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

就违反” Java编译器有没有可能使这个更舒适的异常呢?我更喜欢IllegalArgumentException,并带有一条消息,如“你试图将一个空对象转换为原始类型,这是不能完成的!”

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

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

+0

NPE似乎没什么问题。可空性注释可能有所帮助。 (** **的Un拳,顺便说一句。) – 2010-03-04 19:27:22

回答

55

按照Java language specification,拆箱通过调用Number.longValue()Number.intValue()等情况有没有特殊的字节码的魔法发生的事情,这是完全一样的,如果你手动调用这些方法。因此,NullPointerException是拆箱null(实际上由JLS授权)的自然结果。

抛出一个不同的异常就要求每一个拆箱转换过程中检查null两次(一次,以确定是否要抛出特殊的例外,一旦时隐方法实际上是调用)。我认为语言设计者认为它不足以证明这一点。

+2

解释为什么会发生一个很大的加 - 样的longValue()或doubleValue()以一种方法被称为空对象。类似线程中的很多答案最终都会说“因为拆箱会抛出NullPointerException” – kiedysktos 2017-02-01 09:52:30

1

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

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

+0

在我的例子返回类型为对象,这将是字符串我可以用Long.valueOf()。它不是被迫成为IllegalArgumentException。我想一个特殊的例外,因为有做了一些魔法的人不知道装箱/拆箱。不过没关系,这是你的意见:) – codevour 2010-03-04 19:38:16

+0

我不明白你的意思强制和神奇的东西,但如果你有一个更具体的问题,请张贴额外的示例代码。诸如变量类型的信息将特别有用。 – Pops 2010-03-04 19:43:12

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或有问题的应用程序日志约定。很难做出通用的。

0

由于Java SE 8也有Optional.ofNullable

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