2010-09-24 2 views
96

Пила эту линию в методе класса, и моя первая реакция заключалась в том, чтобы высмеять разработчика, который его написал. Но потом я решил, что должен убедиться, что сначала был прав.Может ли «это» когда-либо быть пустым в Java?

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

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

+99

Всегда высмеивать сначала и спрашивать позже. Легче извиниться, чем вернуть золотую возможность оторвать кого-то в шквал серой. –

+0

Я тоже думал ... На самом деле нужно было проверить аннотации, чтобы убедиться, что это не мое ... Сколько раз я писал: –

+5

+1 для термина «шквал серой». –

ответ

78

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

ПСБ говорит:

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

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


Ресурсы:

+0

Использование его может, однако, не скомпилироваться. Если он компилируется, тогда он безопасен в использовании. –

+0

Разве это просто чепуха, чтобы сделать такую ​​проверку, или это действительно мешает Java-язык, что такое может случиться? I.e - это исключение нулевого указателя, которое было выбрано перед вводом метода или только при попытке доступа к элементу? В сопоставимых ситуациях на других языках (в частности, на C++) этот случай является неопределенным поведением, и язык не будет активно предотвращать такой сценарий. –

+4

Я не знаю глубоко о Java, но в C++ метод this этого метода может быть NULL. Поэтому я не совсем уверен, что это достаточная причина в Java. – kennytm

57

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

+38

_am_ Я жив ?! o god, я больше не знаю – Claudiu

+7

Cogito ergo sum –

+7

Sum ergo this ... –

3

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

2

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

7

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

+2

Я предполагаю, что через отражение мы можем установить внешнее значение этого значения в null. может быть апрельской дурацкой шуткой на кого-то, когда он получил исключение из null-указателя в ссылке «Outer.this.member» – irreputable

1

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

0

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

3

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

7

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

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

this = null; 

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

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

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

true = new Boolean(true); 
true = false; 
+0

Хороший объяснительный друг. –

+0

@PankajSharma Спасибо :) – sactiw

+0

Я нашел это, потому что я хотел посмотреть, могу ли я использовать 'this = null'. Мой экземпляр был в android, где я хотел удалить представление и установить для объекта, обрабатывающего представление, значение null. Затем я хотел использовать метод 'remove()', который бы удалял фактический вид, а затем объект-обработчик был бы бесполезным, поэтому я хотел его обнулить. – Yokich

0

Нормальный this никогда не может быть в режиме реального времени Java кода null, и ваш пример использует нормальный 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 [email protected] 
Exception in thread "main" java.lang.NullPointerException 
     at Outer.main(Outer.java:19) 

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

Фактически, если вы придерживаетесь конверта «Чистая Java», вы не можете это сломать.

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

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

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

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


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

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