Это потому, что разыменование происходит всегда, когда нет имени. Значение загружается в стек операнда, а затем передается одному из кодов операций JRE, которые его разыскивают. Тем не менее, стек операнда не имеет имени для связывания с нулевым значением. Все, что у него есть, - «null». С помощью некоторого умного кода отслеживания времени выполнения можно получить имя, но это добавит накладные расходы с ограниченным значением.
Из-за этого не существует опции JRE, которая включит дополнительную информацию для исключений из нулевого указателя.
В этом примере ссылка хранится в локальном слоте 1, который сопоставляется локальному имени переменной.Но разыменовать происходит в invokevirtual инструкции, которая только видит «нулевое» значение в стеке, а затем бросает исключение:
15 aload_1
16 invokevirtual #5
равноценны бы нагрузка массива с последующим разыменованием, но в этом случае нет никакого имени для сопоставления с значением «null», просто индексом другого значения.
76 aload 5
78 iconst_0
79 aaload
80 invokevirtual #5
Вы не можете выделить имена статически каждую команду либо - это пример дает много байткода, но вы можете видеть, что команда разыменовать получит либо objA или objB, и вам нужно будет отслеживать этот динамически сообщать правильный, поскольку обе переменные потока в одной и той же инструкции разыменовывания:
(myflag ? objA : objB).toString()
Это действительно никогда не было проблемой для меня за 8 лет профессионального профессионала Java. Если у вас есть много ссылок, которые могут быть нулевыми в одной строке, возможно, пора разбить ее на несколько строк. – MattC
@mattc, вы никогда не работаете с кодом библиотеки других народов? –
@MattC: Это часто возникает, когда вам нужно вызвать функцию с несколькими аргументами в условии середины длинного блока if-else-if. Разбить его на несколько строк означало бы поднятие и объявление кучки фиктивных переменных до вершины 'if'. Я бы сказал, что в большинстве случаев это было бы более проблематичным с точки зрения удобочитаемости кода и стиля. – kpozin