Що є на Java?


252

Що таке null?

Це nullпримірник чого-небудь?

Який набір nullналежить?

Як вона представлена ​​в пам'яті?


yegor256. Про null від JLS. "Null Literal. Null type має одне значення, нульове посилання, представлене null literal null, яке формується з символів ASCII. Null Literal завжди має тип null." Про пункти в статті. "Змінні та неповні об'єкти" - це особливість. 'Slow Failed' - це здатність дизайну. "Комп'ютерне мислення проти об'єктного мислення" - це лише два способи мислення. "Неоднозначний семантичний" занадто суб'єктивний. "Спеціальна робота з помилками" - це ще один тип роботи з помилками. Null - це буквальне чи що-небудь інше, вказане в JLS, на відміну від того, що це не добре чи погано.
Олексій Кислицин

Відповіді:


310

Чи нульовий примірник чогось?

Ні, немає типу, який nullє instanceof.

15.20.2 Оператор порівняння типів instanceof

RelationalExpression:
    RelationalExpression instanceof ReferenceType

Під час виконання результатом instanceofоператора є, trueякщо значення RelationalExpression не є nullі посилання може бути передане на ReferenceType без підвищення a ClassCastException. Інакше результат є false.

Це означає , що для будь-якого типу Eі R, для будь-якого E o, де o == null, o instanceof Rзавжди false.


До якого набору належить "null"?

JLS 4.1 Види типів та значень

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


Що таке нуль?

Як зазначено вище в цитаті JLS, на практиці ви можете просто зробити вигляд, що це "просто спеціальний буквальний текст, який може бути будь-якого референтного типу".

У Java null == null(це не завжди так в інших мовах). Зауважте також, що за контрактом він також має це особливе майно (від java.lang.Object):

public boolean equals(Object obj)

Для будь-якого нереферентного nullзначення x, x.equals(null)слід return false.

Це також значення за замовчуванням (для змінних, які їх мають) для всіх типів посилань:

JLS 4.12.5 Початкові значення змінних

  • Кожна змінна клас, змінна інстанція або компонент масиву ініціалізуються зі значенням за замовчуванням, коли воно створюється:
    • Для всіх типів посилань значенням за замовчуванням є null.

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

Є й інші способи використання. Візьмемо реальний приклад із java.lang.System:

public static Console console()

Повертає : системна консоль, якщо така є, інакше null.

Це дуже поширена схема використання: nullвикористовується для позначення неіснуючого об'єкта.

Ось ще один приклад використання цього разу від java.io.BufferedReader:

public String readLine() throws IOException

Повертає : Stringмістить вміст рядка, не враховуючи жодних символів завершення рядка, або nullякщо досягнуто кінця потоку.

Отже, readLine()повертався б instanceof Stringдля кожного рядка, поки він нарешті не повертає а, nullщоб означати кінець. Це дозволяє обробляти кожен рядок наступним чином:

String line;
while ((line = reader.readLine()) != null) {
   process(line);
}

Можна розробити API так, щоб умова закінчення не залежала від readLine()повернення null, але можна побачити, що ця конструкція має перевагу зробити речі стислими. Зауважте, що з порожніми рядками немає проблеми, оскільки порожній рядок "" != null.

Візьмемо ще один приклад, цього разу з java.util.Map<K,V>:

V get(Object key)

Повертає значення, для якого відображено вказаний ключ, або nullякщо ця карта не містить відображення ключа.

Якщо ця карта дозволяє nullзначення, то повернене значення nullне обов'язково вказує на те, що карта не містить відображення ключа; можливо також, що карта явно відображає ключ до null. containsKeyОперація може бути використана , щоб відрізнити ці два випадки.

Тут ми починаємо бачити, як використання nullможе ускладнити речі. Перше твердження говорить про те, що якщо ключ не відображений, nullвін повертається. Друге твердження говорить, що навіть якщо ключ відображений, nullйого також можна повернути.

На відміну від цього, java.util.Hashtableспрощує роботу, не дозволяючи nullключі та значення; його V get(Object key), якщо повертається null, однозначно означає , що ключ не відображається.

Ви можете прочитати решту API і знайти, де і як nullвикористовується. Майте на увазі, що вони не завжди є найкращими прикладами практики .

Взагалі кажучи, nullвикористовуються як особливе значення для позначення:

  • Неініціалізована держава
  • Умова припинення
  • Неіснуючий об’єкт
  • Невідоме значення

Як вона представлена ​​в пам'яті?

На Яві? Ніхто з ваших проблем. І найкраще так зберігати.


Це nullгарна річ?

Зараз це є прикордонним суб'єктивним. Деякі люди кажуть, що це nullвикликає багато помилок програміста, яких можна було уникнути. Деякі кажуть, що мовою, що NullPointerExceptionнагадує Java, корисно використовувати її, оскільки ви не зможете швидко помилитися в програмістських помилках. Деякі люди уникають nullвикористання об'єкта Null , тощо.

Це сама по собі величезна тема, тому її краще обговорити як відповідь на інше питання.

Я закінчу це цитатою самого винахідника null, CAR CAR Hoare (про швидку славу):

Я називаю це моєю помилкою в мільярд доларів. Це був винахід nullпосилання в 1965 році. У той час я розробляв першу комплексну систему для посилань на об'єктно-орієнтованій мові (ALGOL W). Моя мета полягала в тому, щоб будь-яке використання посилань було абсолютно безпечним, а перевірка виконувалась автоматично компілятором. Але я не міг протистояти спокусі поставити nullпосилання просто тому, що це було так просто здійснити. Це призвело до незліченних помилок, уразливості та збоїв у системі, які, ймовірно, спричинили біль і шкоду в мільярд доларів за останні сорок років.

Відео цієї презентації йде глибше; це рекомендований годинник.


4
Нульові посилання існували в LISP (as NIL) в 1960 році, і, ймовірно, і раніше. Але я не думаю, що Хоар справді намагається претендувати на винахід нульових посилань у цій цитаті.
Стівен С

7
Хоар не намагається претендувати на винахід нульових посилань; він просто стверджує, що зробив їх доступними в особливо впливовому місці. Є багато мов, включаючи Java, які, очевидно, взяли натхнення у Algol, і якщо їх використання нульових посилань було частково натхнене або скопійоване з Algol, Хоаре вірно взяти на себе якусь провину за вартість цих. Однак я вважаю, що його оцінка досить низька. Трильйон доларів може бути ближче до справжньої вартості.
cjs

32

Чи нульовий примірник чогось?

Ні. Тому null instanceof Xповернемось falseдо всіх класів X. (Не обманюйте той факт, що ви можете призначити nullзмінну, тип якої є типом об'єкта. Строго кажучи, призначення передбачає неявне перетворення типу; див. Нижче.)

До якого набору належить "null"?

Це єдиний член нульового типу, де нульовий тип визначається наступним чином:

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

Що таке нуль?

Дивись вище. У деяких контекстах nullвикористовується для позначення "ніякого об'єкта" або "невідомого" або "недоступного", але ці значення є специфічними для застосування.

Як вона представлена ​​в пам'яті?

Це конкретна реалізація, і ви не зможете побачити представлення nullв чистій програмі Java. (Але nullпредставлений як нульова адреса / покажчик машини у більшості, якщо не у всіх реалізаціях Java.)


14

Що таке нуль?

Це нічого.

Чи нульовий примірник чогось?

Ні, як це ніщо. Це не може бути примірником будь-якої речі.

До якого набору належить null?

Немає жодного набору

Як вона представлена ​​в пам'яті?

Якщо деякі орієнтири на нього такі:

Object o=new Object();

У купі пам'яті деякий простір, призначений новоствореному об'єкту. І o вкаже на цей відведений простір у пам'яті.

Тепер o=null;

Це означає, що тепер o не вказуватиме на цей простір пам'яті об'єкта.


1
"Тепер o = null; це означає, що o не буде вказувати на цей простір пам'яті об'єкта." Я думаю, що таким чином працює збір сміття в JAVA
Hardik Mishra

9

Ні, це не примірник нічого, instanceof завжди буде помилковим.


7

Ключове слово null - це буквальне значення, яке представляє нульову посилання, яке не відноситься до жодного об'єкта . null - значення за замовчуванням змінних типу опорного типу.

Також, можливо, подивіться

null: Словник Java


2
Це не ключове слово, це буквальне слово . Погана якість та ненормативне цитування.
Маркіз Лорн

6

Null не є екземпляром жодного класу.

Однак ви можете призначити null змінним будь-якого типу (об'єкт або масив):

 // this is false   
 boolean nope = (null instanceof String);

 // but you can still use it as a String
 String x = null;
 "abc".startsWith(null);

6

Нуль у Java (тм)

У C і C ++ "NULL" - це константа, визначена у файлі заголовка, зі значенням на зразок:

    0

або:

    0L

або:

    ((void*)0)

залежно від параметрів компілятора та моделі пам'яті. NULL, власне кажучи, не є частиною C / C ++.

У Java (tm) "null" - це не ключове слово, а особливий літерал нульового типу. Він може бути переданий до будь-якого еталонного типу, але не до будь-якого примітивного типу, наприклад, int або boolean. Нульовий літерал не обов'язково має значення нуль. І неможливо привести до нульового типу або оголосити змінну цього типу.


5

Представлення байт-коду

Java nullмає пряму підтримку JVM: для її реалізації використовуються три інструкції:

  • aconst_null: наприклад, щоб встановити змінну nullяк вObject o = null;
  • ifnullі ifnonnull: наприклад, для порівняння об'єкта з nullяк уif (o == null)

Розділ 6 «Набір інструкцій щодо віртуальної машини Java» потім згадує про ефекти nullінших інструкцій: він підказує NullPointerExceptionдля багатьох з них.

2.4. "Посилання та типи цінностей" також згадуються nullв загальних рисах:

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


4

nullце особлива цінність, це не примірник нічого. З очевидних причин це не може бути instanceofнічого.


3

null- це особливе значення, яке не є примірником жодного класу. Це пояснюється наступною програмою:

public class X {
   void f(Object o)
   { 
      System.out.println(o instanceof String);   // Output is "false"
   }
   public static void main(String[] args) {
      new X().f(null);
   }
}

6
Єдине, що показує приклад - nullце не примірник String.
Саша Чедигов

4
Якщо ви змінили підпис void f(String o), це матиме більше сенсу.
Тіло,

2

null в Java схожий / схожий на nullptr в C ++.

Програма на C ++:

class Point
{
    private:
       int x;
       int y;
    public:
       Point(int ix, int iy)
       {
           x = ix;
           y = iy;
       }
       void print() { std::cout << '(' << x << ',' << y << ')'; }
};
int main()
{
    Point* p = new Point(3,5);
    if (p != nullptr)
    {
       p->print();
       p = nullptr;
    }
    else
    {
        std::cout << "p is null" << std::endl;
    }
    return 0;
}

Та сама програма на Java:

public class Point {
    private int x;
    private int y;
    public Point(int ix, int iy) {
        x = ix;
        y = iy;
    }
    public void print() { System.out.print("(" + x + "," + y + ")"); }
}
class Program
{
    public static void main(String[] args) {
        Point p = new Point(3,5);
        if (p != null)
        {
            p.print();
            p = null;
        }
        else
        {
            System.out.println("p is null");
        }
    }
}

Тепер ви зрозуміли з наведених вище кодів, що в Java є нульовим? Якщо ні, то я рекомендую вам вивчити покажчики на C / C ++, і тоді ви зрозумієте.

Зауважте, що в C, на відміну від C ++, nullptr не визначено, але замість нього використовується NULL, який також може бути використаний і в C ++, але в C ++ nullptr є більш кращим, ніж просто NULL, оскільки NULL у C завжди пов'язаний з покажчиками, і це це, тому в C ++ суфікс "ptr" був доданий до кінця слова, а також усі літери тепер малі, але це менш важливо.

У Java кожна змінна класу типу непримітивна завжди посилається на об’єкт цього типу або успадковується, а null є нульовим посиланням на об’єкт класу, але не є нульовим вказівником, тому що в Java немає такого поняття "покажчик", а посилання на клас Об'єкти використовуються замість цього, а null в Java пов'язаний з посиланнями на об'єкт класу, тому ви можете також називати його як "nullref" або "nullrefobj", але це довго, тому просто називайте його "null".

У C ++ ви можете використовувати покажчики та значення nullptr для необов'язкових членів / змінних, тобто член / змінна, яка не має значення, а якщо вона не має значення, то вона дорівнює nullptr, тому як null в Java може бути використаний, наприклад.


1

У Java існує дві основні категорії типів: примітивний та референтний . Змінні, оголошені значеннями зберігання примітивного типу; змінні, оголошені посиланнями на сховища еталонного типу.

String x = null;

У цьому випадку оператор ініціалізації оголошує змінні "x". "X" зберігає посилання на рядок. Тут нульово . Перш за все, null не є дійсним екземпляром об'єкта, тому для нього не виділено пам'яті. Це просто значення, яке вказує на те, що в даний час посилання на об'єкт не посилається на об'єкт.


0

На мій погляд, цікавий спосіб побачити null в java - це бачити його як щось, що НЕ позначає відсутність інформації, а просто як буквальне значення, яке може бути присвоєне посиланням будь-якого типу. Якщо ви подумаєте про це, якби він позначав відсутність інформації, тоді для a1 == a2 правда не має сенсу (у випадку, якщо їм обом було призначено значення null), оскільки вони справді могли вказувати на будь-який об’єкт (ми просто не знаю, на які об’єкти вони повинні вказувати) ... До речі, null == null повертає true у Java. Якщо java, наприклад, буде як SQL: 1999, тоді null == null повернеться невідомим (булеве значення в SQL: 1999 може приймати три значення: true, false та unknown, але на практиці невідоме реалізується як null в реальних системах) ... http://en.wikipedia.org/wiki/SQL


0

Коротка та точна відповідь, яка формально відповідає на всі ваші запитання від JLS:

3.10.7. Нульовий літерал

Тип null має одне значення - нульове посилання, представлене нульовим буквальним null, яке формується з символів ASCII.

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

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

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