Может ли это быть в Java нулевым?

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

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

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

 Nathan Feger24 сент. 2010 г., 22:53
@Blindy даст +1 для примера кода.
 Marty Pitt24 сент. 2010 г., 20:37
+1 за термин "шквал серы".
 Bryce Fischer24 сент. 2010 г., 19:33
Я тоже так думал ... На самом деле пришлось проверять аннотации, чтобы убедиться, что это не мое ... Сколько раз я писал:
 Nathan Feger27 сент. 2010 г., 23:10
@ Роджер дал секрет +1 где-то. :)
 Rune FS29 июл. 2011 г., 19:25
Хотя очень маловероятно, что (несмотря на общее согласие) на самом деле может произойти, что тест вернет false
 galets25 сент. 2010 г., 01:59
немного насмешек идет долго
 Blindy25 сент. 2010 г., 18:28
@ Натан Фегер, Роджер понял! : D
 Roger Pate24 сент. 2010 г., 23:26
 RBerteig24 сент. 2010 г., 23:35
+1 за "убедитесь, что я был прав первым"
 Joel Etherton24 сент. 2010 г., 19:31
Всегда высмеивать сначала, а потом вопрос. Проще извиниться, чем вернуть прекрасную возможность сорвать кого-то в шквале серы.
 Blindy24 сент. 2010 г., 20:59
Вы знаете, что смешного? Это может произойти в C # из-за ошибки компилятора!
 Andrei Rînea01 нояб. 2010 г., 14:20
ну в C # это может быть нулевым. В некоторых крайних случаях. У меня был тот же импульс: высмеивать присоску, но потом я просто успокоился. Посмотрите здесь:stackoverflow.com/questions/2464097/...

Ответы на вопрос(10)

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

Нормальныйthis никогда не может бытьnull в реальном коде Java1, а ваш пример использует нормальный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 выражение будет оцениватьnull2.

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

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

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

Решение Вопроса

Нет, это не может. Если вы используетеthisтогда вы в инстанции такthis не нуль

JLS говорит:

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

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

Ресурсы :

JLS -this ключевое слово
 Mark Peters24 сент. 2010 г., 19:37
@KennyTM: этого достаточно в Java. Если вы используетеthis ключевое слово и оно компилируется, оно не равно нулю, когда вы его наблюдаете. Но, как говорят другие, это не мешает NPE при попытке вызвать метод, например, Но это совершенно не зависит от вашего метода как метода, и нулевая проверка внутри метода ничего не изменит.
 Colin Hebert29 июл. 2011 г., 16:16
@Rune FS Тогда это все еще Java? (Как язык)
 Mark Peters24 сент. 2010 г., 19:34
@Frustrated: в статическом методе или статическом инициализаторе, да. Или RHS статического присвоения + декларация.
 Claudiu24 сент. 2010 г., 19:34
исключение нулевого указателя в чем-то вродеfoo.bar() будет брошен, когдаfoo обнаружено, чтоnull, это происходит перед входом в метод, но реальная история состоит в том, что нет метода, который можно попытаться вызвать.
 Roger Pate24 сент. 2010 г., 23:29
@ Кенни: не безнеопределенное поведениехотя, если вы знаете детали своей реализации, вы можете использовать ее.
 Mark Peters24 сент. 2010 г., 19:33
@Johannes:this будет компилироваться только тогда, когда он используется в контексте экземпляра. Если кто-то попытается вызвать метод экземпляра без предоставления экземпляра, он не будет скомпилирован дляих, или они получат NPE при попытке вызвать его на объекте. Поведение во время выполнения здесь в основном не имеет значения, если вы не сделаете какую-то сумасшедшую манипуляцию с байт-кодом.
 Johannes Schaub - litb24 сент. 2010 г., 19:31
Это просто чепуха, чтобы делать такую ​​проверку, или это на самом деле предотвращается языком Java, что такое может произойти? Т.е. исключение пустого указателя выдается перед входом в метод или только при попытке доступа к члену? В сопоставимых ситуациях в других языках (в частности, в C ++) это случай неопределенного поведения, и язык не будет активно предотвращать такой сценарий.
 Rune FS29 июл. 2011 г., 14:47
Первый раз я видел неправильный ответ с таким количеством голосов. Действительно возможно создать байт-код, который приведет к тому, что тест будет ложным
 FrustratedWithFormsDesigner24 сент. 2010 г., 19:32
@Mark Peters: Какие обычаи могут не скомпилироваться? Использование в статическом классе - единственное, о чем я могу думать прямо сейчас.
 Adrian Crețu06 сент. 2016 г., 17:08
Я бы не подписался на этот окончательный ответ, даже если он имеет полный смысл. У меня есть отчеты о сбоях для приложения Android, где это == null, когда метод экземпляра вызывается сразу после того, как переменная обнуляется из другого потока. Фактический вызов проходит, даже если переменная равна нулю, и сбой при попытке прочитать элемент экземпляра :)
 kennytm24 сент. 2010 г., 19:32
Я не знаю глубоко о Java, но в C ++this метода экземпляра может быть NULL. Поэтому я не совсем уверен, что это достаточная причина для Java.
 Mark Peters24 сент. 2010 г., 19:31
Однако его использование может не скомпилироваться. Если он компилируется, то его можно использовать безопасно.
 Rune FS29 июл. 2011 г., 18:14
@ Колин, на каком языке кодпризвание вышеописанный метод написан на самом деле не влияет на то, в каком коде написан вышеупомянутый код, не так ли?
 Stephen C15 мая 2016 г., 07:26
«Действительно возможно создать байт-код, который приведет к тому, что тест будет ложным», Однако, если эти байт-коды не могут быть сгенерированыСоответствует JLS Компилятор Java, И загруженный / запущенный JVM (с включенным верификатором), тогда вы не говорите о подлинном методе Java.

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

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

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

 JD Isaacks24 сент. 2010 г., 22:41
Я часто задаюсь вопросом, нахожусь ли я в аду.
 Ben Zotto24 сент. 2010 г., 20:56
Sum Ergo это ...
 Martin Smith24 сент. 2010 г., 19:40
Мыслю, следовательно, существую
 Claudiu24 сент. 2010 г., 19:33
я Я живой ?! о боже, я больше не знаю
 Android Killer08 июл. 2015 г., 07:23
очень коротко и подробно объяснено ...
 Roger Pate24 сент. 2010 г., 23:32
@ Джон: Вы есть. Часть пытки в том, что ты не можешь это подтвердить.
 Johannes Schaub - litb24 сент. 2010 г., 21:48
@nikie В некотором смысле это само собой разумеющееся. Даже в C ++ любая программа, где это происходит, имеет неопределенное поведение. Это также может произойти для виртуальных функций в GCC:ideone.com/W7RmU .
 Niki24 сент. 2010 г., 21:09
Вы делаете это звучит какthis != null был самоочевиден. Это не так - в C ++, например,this вполне может бытьNULL, для не виртуального метода.
 Rune FS10 февр. 2013 г., 08:11
@ JohannesSchaub-litb Это неправда, что поведение программы на c ++ с нулевым указателем для этого не определено. Это определено до тех пор, пока вы не разыщите это

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

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

this = null;

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

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

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

true = new Boolean(true);
true = false;
 Pankaj Sharma13 июн. 2014 г., 12:29
Хорошее объяснение друг.
 sactiw07 дек. 2015 г., 17:06
@ Хорошо, вопрос точно говорит о языке Java, более того, я не сталкивался ни с одним языком, где разрешено устанавливать это = null. То есть, если такие языки существуют, то я сильно сомневаюсь, что «это» в таких языках будет иметь тот же контекст и идеологию.
 Foon04 дек. 2015 г., 16:31
Не уверен, что согласен с вашими требованиями. (по крайней мере, средняя часть; lvalue-часть в порядке ... хотя я почти уверен, что на самом деле существуют неработающие языки, которые позволяют вам назначить, например, true = false (и даже языки, которые я бы не назвал неработающими, могут разрешить это с помощью Отражение или подобная хитрость)). В любом случае, если у меня есть какой-то объект foo, и я должен был это сделать (игнорируя, что это незаконно) foo.this = null, foo все равно будет указывать на память, и поэтому JVM не будет собирать мусор.
 sactiw13 июн. 2014 г., 14:59
@PankajSharma Спасибо :)
 Yokich03 июл. 2015 г., 09:17
Я нашел это, потому что хотел посмотреть, смогу ли я использоватьthis = null, Мой экземпляр был в Android, где я хотел удалить представление и установить объект, обрабатывающий представление, в нуль. Тогда я хотел использовать методremove() который удалил бы фактическое представление, и тогда объект-обработчик был бы бесполезным, поэтому я хотел обнулить его.

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

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

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

 irreputable24 сент. 2010 г., 23:01
Я думаю, что с помощью отражения мы можем установить внешнее значение this равным нулю. может быть апрельской дурацкой шуткой с кем-то, когда он получил исключение нулевого указателя в ссылкахOuter.this.member

Ваш ответ на вопрос