2010-03-04 52 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))); 
相關問題