Почему в Java есть «NullPointerException», когда в Java нет указателей? - PullRequest
14 голосов
/ 07 мая 2010

Почему я получаю исключение под названием NullPointerException, если в Java нет такого понятия, как указатель?

Ответы [ 6 ]

10 голосов
/ 07 мая 2010

В Java нет указателей общего назначения , которыми можно легко манипулировать, добавляя и вычитая произвольные значения, как в C. Это может привести к всевозможным проблемам для неиспользуемых ими.

Тем не менее, Java по-прежнему необходимо различать объект и «нет объекта».Это просто имя исключения, которое означает, что вы пытаетесь использовать ссылку на объект, за которой нет вспомогательного объекта.

Вы могли бы так же легко назвать его NoObjectException или DereferenceException, или одним из множества других имен, чтобы минимизировать вероятность того, что люди будут думать, что Java имеет указатели общего назначения.NullPointerException - это то, что выбрали создатели языка, вероятно потому, что они привыкли к кодированию на C и / или C ++.

7 голосов
/ 07 мая 2010

Да, это одна из первых неприятных вещей, которые я узнал, изучая Java LOL. Это действительно должно называться NullReferenceException, NoObjectException или DereferenceException, как упоминалось paxdiablo. Ссылки даже не должны быть представлены внутри как указатели, и вы не должны заботиться. «Большинство виртуальных машин, включая дескрипторы использования Sun, а не указатели. Дескриптор - это указатель на указатель, так кто знает, как они его используют?» О, виртуальная машина Java от Microsoft на самом деле использует указатели, а не дескрипторы, так что давайте разберемся.

4 голосов
/ 07 мая 2010

Технически это правильно, это действительно должно называться NullReferenceException

2 голосов
/ 07 мая 2010

Потому что внутренние переменные объекта являются указателями на эти объекты. Однако вы не получите значение указателя, кроме как путем вызова 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;
}
0 голосов
/ 07 мая 2010

Поскольку все переменные (в правой части присваивания), которые вы объявляете, являются ссылками на некоторые объекты в пространстве кучи. Если ссылка не указывает куда-либо, то при обращении к этой переменной выдается исключение nullpointerexception.

0 голосов
/ 07 мая 2010

Если у вас есть объект с, скажем, списком в качестве атрибута, и вы явно не выделяете для него место, работающая программа выдаст вам эту ошибку.

Загляните в отладчик (Eclipse или что-то еще), чтобы увидеть, что хранит ваши объекты, если вы не инициализируете их должным образом, и тогда все будет довольно ясно.

Я думаю, что это было сделано для того, чтобы было понятие между объектами, которые имеют пространство в памяти, и объектами, которые не имеют.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...