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

时间:2010-05-07 08:58:58

标签: java pointers nullpointerexception

如果在Java中没有指针这样的概念,为什么会出现一个名为NullPointerException的异常?

6 个答案:

答案 0 :(得分:10)

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

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

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

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

答案 1 :(得分:7)

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

答案 2 :(得分:4)

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

答案 3 :(得分:2)

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

答案 4 :(得分:0)

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

答案 5 :(得分:-1)

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

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

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