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

为什么我得到一个名为NullPointerException的exception,如果在Java中没有指针这样的概念?

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

Java中没有通用指针,您可以通过添加和减去C中的任意值来轻松操作。这可能会导致那些未使用它们的各种问题。

但是,Java仍然需要区分对象和“无对象”。 它只是exception的名称,这意味着您正在尝试使用其后面没有支持对象的对象引用。

您可以轻松地将其NoObjectExceptionDereferenceException ,或者其他众多名称之一,以最大限度地减少人们认为Java具有通用指针的可能性。

NullPointerException是语言创建者选择的,可能是因为他们习惯于用C和/或C ++编码。

从技术上讲,这是正确的,它确实应该被称为NullReferenceException

因为内部对象变量是指向这些对象的指针。 但是,除了在大多数JVM实现上调用System.identityHashCode(object)之外,您不会获得指针值,而JVM实现会返回指向该对象的指针。

编辑:你几乎没事,我几乎错了:identityHashCode比只返回一个指针要复杂得多。 我刚看了一下JVM源代码,他们实现了一些哈希码生成器。 但是,至少在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; } 

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

如果你有一个对象让我们说一个列表作为属性而你没有为它显式分配空间,那么正在运行的程序会抛出你的错误。

查看调试器(Eclipse或不是什么),以便在未正确初始化它们时查看对象的内容,然后事情就会非常清楚。

我认为这样做是为了在存储器中具有空间的对象与不具有空间的对象之间存在一种概念。