为什么Java在Java中没有指针时会出现“NullPointerException”?

问题描述:

如果在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

是的,这是我学习Java LOL时学到的第一件烦人的事情之一。 它确实应该被称为NullReferenceException,NoObjectException或DereferenceException作为paxdiablo提到。 引用甚至不必将内部表示为指针,您不应该在意。 “大多数虚拟机包括Sun的使用句柄,而不是指针,句柄是指向指针的指针,所以谁知道他们是如何使用它的? 哦微软的Java虚拟机实际上使用指针而不是句柄,所以去图。

+0

但是,引用不过是一个不变的指针,至少在概念上,因此...... – Ingo 2013-10-12 21:31:52

没有通用爪哇指针,你可以很容易地通过添加和减去像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

从技术上讲这就是正确的,它真的应该叫的NullReferenceException

+1

引用与指针相同。说一个同义词必须使用,而不是另一个是无稽之谈。 – Val 2013-08-19 10:07:52

因为内部对象变量是指向那些对象。但是,除了在大多数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

如果你有一个假设列表作为一个属性,你不明确为其分配空间的对象,正在运行的程序会抛出这样的错误。

当你没有正确地初始化它们,然后事情会非常清楚的时候,调查一下调试器(Eclipse或者什么不是),看看你的对象是什么。

我认为这样做是为了在对象之间存在一个空间在内存和不存在空间的概念。

因为所声明的所有变量(在赋值的RHS上)都是对堆空间中某些对象的引用。如果引用没有指向任何地方,那么访问该变量将抛出nullpointerexception。