「これ」はJavaでnullになる可能性がありますか?


109

クラスメソッドでこの行を見て、私の最初の反応は、それを書いた開発者をあざ笑うことでした。

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

その行はfalseと評価されますか?


104
常に最初は嘲笑し、後で質問する。あふれんばかりに誰かを壊す絶好の機会を取り戻すよりも、謝罪する方が簡単です。
Joel Etherton、2010

5
「ブリムストーンの突風」という用語の+1。
Marty Pitt

13
面白いもの知ってる?これは、コンパイラのバグが原因でC#で発生する可能性があります。
ブリンディ

1
@Blindyはコードサンプルに+1を与えます。
Nathan Feger、2010

6
C#では、nullでもかまいません。一部のエッジケース。私は同じ衝動を持っていました:吸盤を嘲笑いましたが、それから私は落ち着きました。ここを見て:stackoverflow.com/questions/2464097/...
アンドレイRînea

回答:


88

いいえ、できません。を使用thisしている場合は、インスタンスにいるのでthisnullではありません。

JLSは言う:

キーワードthisは、1次式として使用される場合、インスタンスメソッドが呼び出されたオブジェクト(§15.12)、または構築されるオブジェクトへの参照である値を示します。

オブジェクトからメソッドを呼び出した場合、オブジェクトが存在するか、NullPointerException前に存在することになります(または、静的メソッドですが、その中では使用できませんthis)。


リソース:


4
Javaについてはよく知りませんが、C ++ではthisインスタンスメソッドのNULLになる可能性があります。したがって、これがJavaで十分な理由であるとは私はまったく確信していません。
kennytm

4
が発見さfoo.bar()れたときにスローされるようなのnullポインタ例外。メソッドに入る前に発生しますが、実際には、呼び出すメソッドはありません。foonull
Claudiu

5
@KennyTM:Javaでは十分です。thisキーワードを使用していて、それがコンパイルされた場合、それを観察してもnullではありません。しかし、他の人が言うように、それはメソッドを呼び出そうとするときのNPEを妨げません。たとえば、それはメソッドとして完全に制御不能であり、メソッド内のnullチェックは何も変更しません。
マークピーターズ

5
@Kenny:未定義の動作がないわけではありませんが、実装の詳細がわかっていれば、それを使用できます。

4
たとえそれが完全に理にかなっているとしても、私はこの決定的な答えに同意しません。変数が別のスレッドからnull化された直後にインスタンスメソッドが呼び出されると、これが== nullであるAndroidアプリのクラッシュレポートがあります。変数がnullであっても実際の呼び出しは通過し、インスタンスメンバーを読み取ろうとするとクラッシュします:)
Adrian Crețu

63

「私は生きているのか」と自問するようなものです。thisnullになることはありません


44
午前私は生きています!oもう神は知らない
Claudiu 2010

this != null自明のように聞こえますか。そうでない- C ++では、例えば、this十分であり得るNULL非仮想メソッドのために、。
Niki

1
@nikieある意味で、それは自明です。C ++でも、これが発生するプログラムはすべて未定義の動作をします。これは、GCCの仮想機能でも発生する可能性があります:ideone.com/W7RmU
ヨハネスシャウブ-litb

8
@ジョン:あなたはそうです。拷問の一部はあなたがそれを確認できないことです。

@ JohannesSchaub-litbこれに対するnull参照を持つc ++プログラムの動作が未定義であることは真実ではありません。これを逆参照しない限り定義されます
Rune FS

9

いいえ、キーワード 'this'自体は、そのクラスのスコープ内にあるそのクラスの現在有効なインスタンス(オブジェクト)を表します。これにより、すべてのフィールドとメンバー(コンストラクターを含む)およびその親クラスの表示可能なインスタンスにアクセスできます。

さらに興味深いことに、設定してみてください。

this = null;

それについて考えますか?どうしてそれが可能になるのか、それはあなたが座っている枝を切るようなものではないでしょうか。キーワード 'this'はクラスのスコープ内で使用できるため、this = null;と言うとすぐに、クラス内の任意の場所で、基本的には、JVMに操作の途中でそのオブジェクトに割り当てられたメモリを解放するように要求します。この操作は、JVMがその操作の終了後に安全に戻る必要があるため、発生させることができません。

また、実行しようとthis = null;するとコンパイラエラーが発生します。理由は非常に単純です。Java(または任意の言語)のキーワードに値を割り当てることはできません。つまり、キーワードを割り当て操作の左側の値にすることはできません。

他の例では、あなたは言うことができません:

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

良い説明友達。
Pankaj Sharma

@PankajSharmaありがとう:)
sactiw

使えるかどうか見たかったので見つけましたthis = null。私のインスタンスはandroidで、ビューを削除し、ビューを処理するオブジェクトをnullに設定したいと考えていました。次にremove()、実際のビューを削除してハンドラーオブジェクトが役に立たなくなるようにするメソッドを使用したかったので、それをnullにしたかったのです。
Yokich、2015

私があなたの主張に同意するかわかりません。(少なくとも中央部分;左辺値の部分は問題ありません...実際には、たとえばtrue = falseを割り当てることができる壊れた言語があると確信しています(そして、壊れたと呼ばない言語でさえ、反射または同様の策略))。とにかく、もし私がオブジェクトfooを持っていて、それが(違法であることを無視して)foo.this = nullを実行した場合、fooは依然としてメモリをポイントするため、JVMはガベージコレクションを行いません。
FOON

@まもなく、質問は正確にJava言語について語っています。さらに、this = nullの設定が許可されている言語に出会ったことはありません。つまり、そのような言語が存在する場合、そのような言語の「これ」が同じコンテキストとイデオロギーを持つことは非常に疑わしいです。
sactiw

7

-target 1.3以前にコンパイルした場合、アウター thisはになることがありますnull。または、少なくとも以前は...


2
リフレクションによって、外側のthisをnullに設定できると思います。参照中にnullポインター例外が発生したときのエイプリルフールのジョークかもしれませんOuter.this.member
評判の悪い

3

いいえ。クラスのインスタンスのメソッドを呼び出すには、インスタンスが存在している必要があります。インスタンスは暗黙的にパラメータとしてメソッドに渡され、によって参照されthisます。もしをthisしてnull、その後のメソッドを呼び出すために何のインスタンスは存在していないと思います。


3

言語がそれを強制するだけでは十分ではありません。VMはそれを強制する必要があります。VMがそれを実施しない限り、Javaで作成されたメソッドを呼び出す前に、nullチェックを実施しないコンパイラーを作成できます。インスタンスメソッド呼び出しのオペコードには、this refをスタックにロードすることが含まれます。http: //java.sun.com/docs/books/jvms/second_edition/html/Compiling.doc.html#14787を参照してください。これをnull参照に置き換えると、実際にテストは偽になります


3

静的クラスメソッドでthisは、はクラスではなくthisインスタンスに関連付けられているため、は定義されていません。this静的なコンテキストでキーワードを使用しようとすると、コンパイラエラーが発生すると思います。


2

法線thisnull実際の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したことを示しています。nullOuter

実際、「Pure Java」の封筒に固執したとしても、これを破ることはできません。

ただし、各Innerインスタンスには非表示のfinal合成フィールド(と呼ばれます"this$0")があり、への参照が含まれていますOuter。本当にトリッキーな場合は、「純粋でない」手段を使用nullしてフィールドに割り当てることができます。

  • あなたUnsafeはそれを行うために使用できます。
  • これを行うには、ネイティブコード(JNIなど)を使用できます。
  • リフレクションを使用してそれを行うことができます。

どちらにしても、結果はOuter.this式がnull2に評価されます。

つまり、資格を持つことが可能です。ただし、プログラムが「Pure Java」の規則に従っている場合は不可能です。thisnull


1-手作業でバイトコードを「書き込み」、実際のJavaとして渡す、BCELなどを使用してバイトコードを微調整する、ネイティブコードにホップして保存されたレジスタを操作するなどのトリックを無視します。IMO、それはJavaではありません。仮に、そのようなことはJVMのバグの結果としても発生する可能性があります。

2-実際には、JLSは動作がどうなるかを述べておらず、とりわけ実装に依存している可能性があります。


1

null参照時にメソッドを呼び出すと、NullPointerExceptionJava VMからがスローされます。これは仕様によるものであるため、Java VMが仕様に厳密に準拠している場合thisは、絶対に準拠しませんnull


1

メソッドが静的である場合、はありませんthis。メソッドが仮想の場合、メソッドthisを呼び出すために、ランタイムはthisポインターを使用してvtableを参照する必要があるため、nullにすることはできません。メソッドが仮想ない場合、はい、それthisがnull である可能性があります。

C#およびC ++は非仮想メソッドを許可しますが、Javaではすべての非静的メソッドが仮想であるため、thisnullになることはありません。


0

tl; dr、 "this"は非静的メソッドからのみ呼び出すことができ、非静的メソッドはnullにできない何らかのオブジェクトから呼び出されることがわかっています。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.