2010-05-07 101 views
12

如果在Java中沒有指針這樣的概念,爲什麼我會得到一個名爲NullPointerException的異常?爲什麼Java在Java中沒有指針時會出現「NullPointerException」?

+32

因爲它*應該*被稱爲'NullReferenceException',但有人沒有想到直。 – skaffman 2010-05-07 08:59:43

+2

這個。我的寵物Java的一個偷窺。 – tzaman 2010-05-07 09:01:21

+1

@tzaman +1我學習的時間越長,我越不喜歡它的不一致性和自我矛盾。 – 2010-05-07 09:09:10

回答

7

是的,這是我學習Java LOL時學到的第一件煩人的事情之一。 它確實應該被稱爲NullReferenceException,NoObjectException或DereferenceException作爲paxdiablo提到。 引用甚至不必將內部表示爲指針,您不應該在意。 「大多數虛擬機包括Sun的使用句柄,而不是指針,句柄是指向指針的指針,所以誰知道他們是如何使用它的? 哦微軟的Java虛擬機實際上使用指針而不是句柄,所以去圖。

+0

但是,引用不過是一個不變的指針,至少在概念上,因此...... – Ingo 2013-10-12 21:31:52

10

沒有通用爪哇指針,你可以很容易地通過添加和減去像C中的任意值操作。這可能會導致各種問題,爲他們沒有使用。

但是,Java仍然需要區分對象和「無對象」。這只是異常的名稱,這意味着您正在嘗試使用沒有背後支持對象的對象引用。

您可以簡單地稱之爲NoObjectExceptionDereferenceException或其他名稱之一,以最大限度地減少人們認爲Java具有通用指針的可能性。

但是NullPointerException是語言創建者選擇的,可能是因爲他們習慣於在C和/或C++中進行編碼。

+0

如果只有null將被包括在類型系統中: -/ – 2010-05-07 09:03:54

+0

@paxidiablo那麼爲什麼地球上他們發明了final而不是使用const。如果你考慮它,最終不像const那樣具有描述性。 – 2010-05-07 09:10:48

+1

因爲const會定義一個常量。 Final與C++中的const稍有不同,因爲您可以延遲設置final,並且一旦設置,就不能更改。在我看來,最後的決定是正確的。一旦你確定了它,那就是它的最終價值。 – paxdiablo 2010-05-07 11:18:49

4

從技術上講這就是正確的,它真的應該叫的NullReferenceException

+1

引用與指針相同。說一個同義詞必須使用,而不是另一個是無稽之談。 – Val 2013-08-19 10:07:52

2

因爲內部對象變量是指向那些對象。但是,除了在大多數JVM實現上調用System.identityHashCode(object)之外,您不會獲得指針值,這會返回指向該對象的指針。

編輯:你幾乎所有的權利,我幾乎是錯的:identityHashCode比只返回一個指針複雜得多。我只看了一下JVM源代碼,並且他們實現了一些hashcode生成器。但是,至少在hashCode(常數?我不知道)是常量的情況下,它們會返回對象指針。這裏是他們的好奇來源:

static inline intptr_t get_next_hash(Thread * Self, oop obj) { 
    intptr_t value = 0 ; 
    if (hashCode == 0) { 
    // This form uses an unguarded global Park-Miller RNG, 
    // so it's possible for two threads to race and generate the same RNG. 
    // On MP system we'll have lots of RW access to a global, so the 
    // mechanism induces lots of coherency traffic. 
    value = os::random() ; 
    } else 
    if (hashCode == 1) { 
    // This variation has the property of being stable (idempotent) 
    // between STW operations. This can be useful in some of the 1-0 
    // synchronization schemes. 
    intptr_t addrBits = intptr_t(obj) >> 3 ; 
    value = addrBits^(addrBits >> 5)^GVars.stwRandom ; 
    } else 
    if (hashCode == 2) { 
    value = 1 ;   // for sensitivity testing 
    } else 
    if (hashCode == 3) { 
    value = ++GVars.hcSequence ; 
    } else 
    if (hashCode == 4) { 
    value = intptr_t(obj) ; 
    } else { 
    // Marsaglia's xor-shift scheme with thread-specific state 
    // This is probably the best overall implementation -- we'll 
    // likely make this the default in future releases. 
    unsigned t = Self->_hashStateX ; 
    t ^= (t << 11) ; 
    Self->_hashStateX = Self->_hashStateY ; 
    Self->_hashStateY = Self->_hashStateZ ; 
    Self->_hashStateZ = Self->_hashStateW ; 
    unsigned v = Self->_hashStateW ; 
    v = (v^(v >> 19))^(t^(t >> 8)) ; 
    Self->_hashStateW = v ; 
    value = v ; 
    } 

    value &= markOopDesc::hash_mask; 
    if (value == 0) value = 0xBAD ; 
    assert (value != markOopDesc::no_hash, "invariant") ; 
    TEVENT (hashCode: GENERATE) ; 
    return value; 
} 
+0

@Daniel只是出於好奇,以及在什麼變量類型中存儲這個指針? – 2010-05-07 09:29:33

+0

指針本身是一個int。因此,在64位系統上,散列可能略有不同(如4個高位字節xord到4個低位字節地址)。 – Daniel 2010-05-07 11:41:11

+2

@知道它返回一個int。但它不是一個指針。這是...(等待它)...散列碼。在某些JVM中,它是地址的函數,但它不一定是。該行爲未由JLS指定。 順便說一句,因爲它是一個散列碼,所以兩個對象可以具有相同的idenityHashCode()值。 我不會downvote,但Daniel的答案的最後一部分是不正確的:它在多個級別上是錯誤的,說identityHashCode值是指針。 – CPerkins 2010-05-07 11:45:11

-1

如果你有一個假設列表作爲一個屬性,你不明確爲其分配空間的對象,正在運行的程序會拋出這樣的錯誤。

當你沒有正確地初始化它們,然後事情會非常清楚的時候,調查一下調試器(Eclipse或者什麼不是),看看你的對象是什麼。

我認爲這樣做是爲了在對象之間存在一個空間在內存和不存在空間的概念。

0

因爲所聲明的所有變量(在賦值的RHS上)都是對堆空間中某些對象的引用。如果引用沒有指向任何地方,那麼訪問該變量將拋出nullpointerexception。

相關問題