Чи є null об’єктом?


119

Чи є nula an Objectу Java?


41
Ні, це не так, і для тих, хто цікавиться, чому таке питання, є мови, де null - це об'єкт, як будь-який, наприклад, Ruby.
JRL

7
У Scala, яка дуже прискіпливо стосується типів, існує тип Null( насправді риса ), що має єдиний екземпляр null.
Карл Смотрич

1
@JRL: Просто з цікавості мені цікаво, як це впливає на те, як працює JRuby ... (я недостатньо знайомий з таким рівнем впровадження, щоб точно знати).
Бенджамін Оукс

Для того, щоб додати коментар @ JrL в - грубий еквівалент Рубі на nullце nil, який є екземпляром NilClass
Еліот Sykes

Або javascript, у якому null instanceof Objectпомилково, але typeof(null)повертається 'object'. Це об’єкт у такому випадку? Хто знає.
Дон Хетч

Відповіді:


166

Якщо null був Об'єктом, він підтримував би такі методи java.lang.Object, як equals(). Однак це не так - будь-який виклик методу на нуль призводить до а NullPointerException.

Ось що на цю тему має сказати специфікація мови Java :

Існує також спеціальний тип null, тип виразу null, який не має назви. Оскільки нульовий тип не має імені, неможливо оголосити змінну типу null або передати на null тип. Нульова посилання є єдиним можливим значенням виразу нульового типу. Нульова посилання завжди може бути передана на будь-який тип посилання. На практиці програміст може ігнорувати нульовий тип і просто робити вигляд, що null - це лише спеціальна буква, яка може мати будь-який тип посилання.

Я думаю, що це можна звести до "null is special".


1
Таким чином, об’єкт у Java є лише об'єктом, якщо він дорівнює або підкласам java.lang.Object. Практично - так. Ви не можете створити клас, який не є підкласом java.lang.Object, але я ніколи не думав про це з більш філософської точки зору
Андреас Долк

Цікаво, що з усіх речей API-документ API дляNullPointerException згадки про " nullоб'єкт" ... :) Але тоді також було гаразд говорити про "нульові покажчики" ...
Lumi

Ви сказали: "Нульова посилання завжди може бути передана на будь-який тип посилання". Отже, чи можемо ми повернути null (typecasted-якщо це дозволено) у методі з типом посилання на об'єкт (return)?
Срічакрадхар

1
@Srichakradhar: так, можемо! Що ви можете дізнатися простіше, спробувавши його в коді, ніж запитуючи тут.
Майкл Боргвардт

1
"Нульова посилання є єдиним можливим значенням виразу нульового типу". Настав час прочитати док. :)
sofs1

32

Відповідно до специфікації Java , nullце тип, який можна присвоїти об'єктній змінній (як значення, як зазначено в коментарі). Однак ви не можете створити інстанціювати або створити змінні цього типу, ви повинні використовувати літерал, nullнаданий компілятором.


8
null - це тип і значення.
Йоахім Зауер

5
nullНазва є «екземпляром» з nullтипу, по- видимому.
страгер

nullне є змінною, а буквальною: JLS, 3.10.7. The Null Literal
Gerold Broser

Re " null- це тип, який можна призначити ": 1) null(у коді) - це нульовий буквальний , а не нульовий тип 2) Типи не можна призначати змінним в Java загалом, див. JLS 4.1: " Є [... ] два види значень даних, які можуть зберігатися у змінних [...]: примітивні значення (§4.2) та опорні значення (§4.3). " Це нульове посилання, яке може бути призначене через nullбуквальне. ... продовження ...
Герольд Брозер

3) об'єкт у " об'єктній змінній ", порівняно із змінною класу, зазвичай не стосується типу, а всього життя. Коли йдеться про тип, його зазвичай називають змінною еталонного типу або, коротше, змінною (типу). Мені відомо 4 типи Java API, які розкривають змінні екземпляра / об'єкта (їх може бути більше): масиви з йогоlength та підкласи java.awt.geom.Point2D.
Герольд Брозер



12

Нульовим є відсутність предмета.


Але нульовий тип присвоюється кожному еталонному типу.
Том Хотін - тайклін

Немає "нульового типу"; null - це специфічне значення непримітивних виразів (тобто посилань; на Java не існує "посилального типу").
Томмі Макгуайр

3
Томмі: JLS 4.1: "Існує також спеціальний нульовий тип, тип виразу null, який не має імені."
Кен


12

JRL написав:

Ні це не так, ...

Як часто, це залежить від того, де ти на це дивишся, кому більше віриш.

Згідно JLS, так, так . Особливо, якщо ви перефразовуєте запитання на тему: "Чи nullбуквальний тип Object?" Крім JLS 4.1 цитованого Майклом Боргвардом вище:

Див. JLS 3.10.7 :

Нульовий літерал завжди має нульовий тип.

та JLS 4.10 :

Підтипами типу T є всі типи U такі, що T є супертипом U та нульовим типом.

або JLS 4.10.2 :

Прямі супертипи нульового типу - це всі типи посилань, крім самого нульового типу.

[Наголоси від мене.]

За компілятором Eclipse 2019-09, це не так :

true.toString();  // Cannot invoke toString() on the primitive type boolean
null.toString();  // Cannot invoke toString() on the primitive type null

Згідно з OpenJDKs 12.0.1 javac це :

true.toString();  // error: boolean cannot be dereferenced
null.toString();  // error: <null> cannot be dereferenced

Де під кутовими дужками випливає, що nullце інший, ніж примітивний тип. І згідно JLS 4.1 :

У мові програмування Java є два типи: примітивні типи (...) та типи посилань (...).

якщо це не той, то інший.


Клавді написав:

null - це щось некрасиво.

Au contraire, nullпрекрасна. Що б ви запропонували замість змінної типу посилання за замовчуванням? Довільна бітова комбінація? Ласкаво просимо, щоб отримати доступ до порушення або, що ще гірше, пекло покажчика!


Йоахім Зауер написав:

null - це тип і значення.

У поєднанні з null є три елементи (див. Також JLS 3.10.7 ):

  1. Нульовий тип (інакше безіменний) .
  2. null Буквальним .
  3. Посилання нульове значення. (Зазвичай скорочується як null value або просто null .)

(1) Зауважимо, що згідно з цитованим вище JLS 4.10.2 , тип null використовує багатократне успадкування не тільки для інтерфейсів, але і для класів. Що ми всі знаємо, це неможливо для нас програмістів прикладних програм.

(2) Нульовий літерал можна уявити як змінну, що визначається як:

JVM_global final null_type null = new null_type();

Зверніть увагу також на JLS 3.9 :

Різні послідовності символів іноді невірно вважаються ключовими словами:

  • nullце не ключове слово, а скоріше нульовий літерал ( §3.10.7 ).

Стосовно null instanceof <any type>

Маючи на увазі JLS 4.10.2 (« нульовий тип - це підтип кожного типу»), null instanceof <any type>слід вважати true, чи не так? На перший погляд, так, але JLS 15.20.2 дає зрозумілу відповідь:

[...] результат від instanceofоператора є , trueякщо значення в ВираженіяОтношеніі НЕnull [...]. Інакше результат єfalse .

[Наголоси від мене.]

Запитайте себе, що має більше сенсу (з точки зору програміста програми):

  • Надання falseта тим самим вказівка ​​на те, що опорний вираз не такого типу, який нам піддається, тобто вказує, що він не посилається на щось корисне

  • або даючи true, таким чином, повідомляючи нас, що вираз оцінює спеціальне посилання, нульове посилання , посилаючись на "об'єкт", ми не знаємо, чи він існує і який має спеціальний нульовий тип, який не має імені, не піддається Ми, але через нульовий буквальний , є підтипом будь-якого типу, включаючи множинне успадкування, і все-таки його слід ігнорувати? Розглянемо також більш практичний приклад:

     class Car implements Vehicle {  
     ...
     Vehicle car = null;
     ...
     boolean b = car instanceof Car;  // True? There's not even an instance
     ...                              // which could be of type Car.

Що також призводить до:

Чому це instanceofне правильний спосіб сказати щось про цеnull об'єкт-об'єкт?

Це називається instanceofне sameorsubtypeof. Це означає, що ми порівнюємо тип екземпляра з типом, а не два типи. Тепер nullозначає: „Не існує примірника”, а якщо немає примірника, немає типу примірника. Очевидно, що порівнювати нічого з чим-небудь не повинноfalse .

Або в "більш" прикладі реального світу:

  • У мене в руках малюнок яблука в реальному розмірі ( = еталонний тип ) з "Великим яблуком" ( = назва базового типу) ) , написаним на ній.
  • Там таблиця ( = купаПереді мною ).
  • Якщо на столі є яблуко ( = екземпляр ), є шнур ( = посилання) ).
  • Я тримаю інший кінець цього шнура в руці ( = контрольна змінна ).
  • Я простежу яблуко уздовж шнура і порівнюю його зі своїм малюнком ( = instanceof ).
  • Якщо яблуко такого ж розміру або більше, ніж на малюнку, до нього застосовується написання «Велике яблуко» ( = вірно ).
  • Якщо вона менша, то не ( = false ).
  • Якщо на столі немає яблука (= немає примірника ), а значить, немає шнура ( = null ), запис не застосовується (або false ). Тому що: чи не одне яблуко є великим яблуком? Ні це не так.


Як підсумовує Майкл: справді "нуль особлива".


2
Apple і null? Ти не боїшся позову? :)
Gábor Lipták

9

Ні, це не примірник класу, а не клас. Це посилання на ніщо.

Редагувати : не читав специфікацію, тому вищевикладене може бути не на 100% точним.


5

Як пояснено в розділі 4.1 Види типів і значень специфікації мови Java, null - це тип, який має одне значення, нульове посилання (і представлений буквальним null):

Існує також спеціальний нульовий тип, тип виразу null, який не має назви. Оскільки нульовий тип не має імені, неможливо оголосити змінну типу null або передати на null тип. Нульова посилання є єдиним можливим значенням виразу нульового типу. Нульова посилання завжди може бути передана на будь-який тип посилання. На практиці програміст може ігнорувати нульовий тип і просто робити вигляд, що nullце лише спеціальний літерал, який може мати будь-який тип посилання.

Можливо, ви хочете прочитати про Null Object Pattern (що я не рекомендую). Дивіться C2 Wiki або Wikipedia про цю схему .



4

Ні, не є об'єктом, оскільки null instanceof Object завжди повертає false, а також є лише один null, а не один для кожного класу.


3
Насправді null instanceof <anytype>повернеться falseтеж.
Бомбе

4

Згідно з Java Spec ,

Існує також спеціальний нульовий літерал, який може бути використаний як значення для будь-якого типу посилань. null може бути призначений будь-якій змінній, крім змінних примітивних типів. З нульовим значенням ви можете не тестувати його наявність. Тому null часто використовується в програмах як маркер, щоб вказати, що якийсь об’єкт недоступний.


4

Java обробляє об'єкти за допомогою посилань. Null - це зрив OO-ності Java, оскільки він опускає вас нижче рівня OO. Ні, це не об'єкт, це ЗНАЧЕННЯ посилання. І це не має нічого спільного з парадигмами об'єктів, але стосується сантехніки Java, яка дозволяє об’єкти.


3

Чи нульовий примірник java.lang.Object? Немає.

Недійсний об’єкт ? залежить від визначення поняття " є ".


2
Object foo = null;
System.out.println(foo.toString()); 

Показ першого рядка nullможе бути призначений типу Object, але другий рядок демонструє, що це, звичайно, не є, Objectі в кінцевому підсумку призводить до "java.lang.NullPointerException


Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.