Может ли это когда-либо быть нулевым в Java? - PullRequest
103 голосов
/ 24 сентября 2010

Увидел эту строку в методе класса, и моей первой реакцией было высмеивание разработчика, который написал это ... Но потом я решил, что должен убедиться, что я был прав первым.

public void dataViewActivated(DataViewEvent e) {
    if (this != null)
        // Do some work
}

Будет ли эта строка когда-либо оценена как ложная?

Ответы [ 10 ]

84 голосов
/ 24 сентября 2010

Нет, не может. Если вы используете this, то вы в экземпляре, поэтому this не равно нулю.

JLS говорит:

При использовании в качестве основного выражения ключевое слово this обозначает значение, которое является ссылкой на объект, для которого был вызван метод экземпляра (§15.12), или на конструируемый объект.

Если вы вызвали метод из объекта, значит, объект существует, или у вас будет NullPointerException раньше (или это статический метод, но тогда вы не можете использовать this в нем).


Ресурсы:

61 голосов
/ 24 сентября 2010

Это все равно что спрашивать себя "Я жив?"this никогда не может быть нулевым

9 голосов
/ 11 октября 2012

Нет, никогда , само ключевое слово 'this' представляет текущий живой экземпляр (объект) этого класса в области действия этого класса, с помощью которого вы можете получить доступ ко всем его полям и членам (включая конструкторы). и видимые из его родительского класса.

И, что еще интереснее, попробуйте установить его:

this = null;

Думаете об этом? Как это может быть возможно, не будет ли это как срезать ветку, на которой вы сидите. Поскольку ключевое слово «this» доступно в рамках класса, то, как только вы говорите, this = null; тогда в любом месте класса вы в основном просите JVM освободить память, выделенную этому объекту, в середине какой-то операции, которую JVM просто не может допустить, поскольку она должна безопасно вернуться после завершения этой операции.

Кроме того, попытка this = null; приведет к ошибке компилятора. Причина довольно проста: ключевому слову в Java (или любом другом языке) никогда не может быть присвоено значение, т.е. ключевое слово никогда не может быть левым значением операции присваивания.

Другие примеры, вы не можете сказать:

true = new Boolean(true);
true = false;
7 голосов
/ 24 сентября 2010

Если вы компилируете с -target 1.3 или более ранней версией, тогда external this может быть null.Или, по крайней мере, раньше ...

3 голосов
/ 28 июля 2011

Недостаточно того, что язык усиливает это.ВМ должна обеспечить его выполнение.Если виртуальная машина не предписывает это, вы можете написать компилятор, который не применяет нулевую проверку перед вызовом метода, написанного на Java.Коды операций для вызова метода экземпляра включают загрузку этой ссылки в стек, см. http://java.sun.com/docs/books/jvms/second_edition/html/Compiling.doc.html#14787. Замена этой переменной на нулевую ссылку действительно приведет к тому, что тест будет ложным

3 голосов
/ 24 сентября 2010

В статических методах класса this не определено, поскольку this связано с экземплярами, а не с классами.Я считаю, что это даст ошибку компилятора при попытке использовать ключевое слово this в статическом контексте.

3 голосов
/ 24 сентября 2010

Нет.Чтобы вызвать метод экземпляра класса, экземпляр должен существовать.Экземпляр неявно передается в качестве параметра методу, на который ссылается this.Если this было null, то не было бы экземпляра для вызова метода.

1 голос
/ 15 мая 2016

Нормальный this никогда не может быть null в реальном коде Java 1 , и в вашем примере используется нормальный this. См. Другие ответы для более подробной информации.

Квалифицированный this должен никогда не быть null, но это можно сломать. Учтите следующее:

public class Outer {
   public Outer() {}

   public class Inner {
       public Inner() {}

       public String toString() {
           return "outer is " + Outer.this;  // Qualified this!!
       }
   }
}

Когда мы хотим создать экземпляр Inner, нам нужно сделать это:

public static void main(String[] args) {
    Outer outer = new Outer();
    Inner inner = outer.new Inner();
    System.out.println(inner);

    outer = null;
    inner = outer.new Inner();  // FAIL ... throws an NPE
}

Вывод:

outer is Outer@2a139a55
Exception in thread "main" java.lang.NullPointerException
        at Outer.main(Outer.java:19)

показывает, что наша попытка создать Inner со ссылкой null на Outer не удалась.

На самом деле, если вы застряли в конверте "Чистая Ява", вы не сможете сломать это.

Однако каждый экземпляр Inner имеет скрытое синтетическое поле final (называемое "this$0"), которое содержит ссылку на Outer. Если вы действительно хитры, можно использовать «не чистые» средства для присвоения null полю.

  • Вы можете использовать Unsafe, чтобы сделать это.
  • Вы можете использовать нативный код (например, JNI) для этого.
  • Вы можете сделать это, используя отражение.

В любом случае, в конечном итоге выражение Outer.this будет иметь значение null 2 .

Короче говоря, возможно для квалифицированного this быть null. Но это невозможно , если ваша программа следует правилам "Чистой Java".


1 - Я обесцениваю уловки, такие как «написание» байт-кодов вручную и выдавая их за реальную Java, настройку байт-кодов с использованием BCEL или аналогичных, или переход в нативный код и использование сохраненных регистров ИМО, это НЕ ЯВА. Гипотетически, такие вещи могут также произойти в результате ошибки JVM ... но я не помню, чтобы каждый видел сообщения об ошибках.

2 - На самом деле, JLS не говорит, каково будет поведение, и это может зависеть от реализации ... среди прочего.

1 голос
/ 25 сентября 2010

Когда вы вызываете метод для ссылки null, NullPointerException будет выброшен из Java VM.Это по спецификации, поэтому, если ваша виртуальная машина Java строго соответствует спецификации, this никогда не будет null.

0 голосов
/ 25 сентября 2010

tl; dr, "this" может вызываться только из нестатического метода, и мы все знаем, что нестатический метод вызывается из некоторого объекта, который не может быть нулевым.

...