instanceofを呼び出す前にnullチェックが必要ですか?


1354

ウィルnull instanceof SomeClass返すfalseか、投げますかNullPointerException


同じタイプのnull以外のオブジェクトでのみ成功するように設計されたCompareまたはEqualsまたは類似のメソッドの「ベストプラクティス」の開始(または非常に早い)行としても「重要」または少なくとも非常に有用です。単一行の「愚かな事件」からあなたを守ります。コードが少ない=バグが少ない。

13
「これは便利ですか?」議論-私は自分のJavaコードを書いたことがないので(仕様がどこにあるのか簡単にわからず、テストをコンパイルするのは簡単ではありません)、現在JavaをJavaScriptに手動で変換しています。私のコードはnull参照で失敗し、これをグーグルすると、受け入れられた回答が表示されました。これは、予期された動作であり、暗黙のnullチェックがないことを確認しました。私の場合、非常に便利です。
Scott Mermelstein 2013

回答:


1839

いいえ、instanceofを使用する前にnullチェックは必要ありません。

x instanceof SomeClassfalseif xですnull

Java言語仕様のセクション15.20.2「タイプ比較演算子instanceof」から

「実行時に、その結果 instanceofオペレータはあるtrueの値ならば関係式が ないnullと参照がにキャストすることができReferenceTypeが 上げずにClassCastException。そうしないと結果がありますfalse。」

したがって、オペランドがnullの場合、結果はfalseになります。


377
現在の動作保証された動作と同じではないtry itため、この答えはより正確です。
ルーク

3
この質問は、内のオブジェクトの平等に関するジョシュア・ブロックの章の間に遊びに来てEffective Java- amazon.com/Effective-Java-Edition-Joshua-Bloch/dp/0321356683
ケビン・メレディス

17
具体的には、項目8で、equals()メソッドでは、1つのinstanceof演算子が2つの目的を果たします。引数がnullでなく、正しい型であることを確認します。「... [S] o個別のnullチェックは必要ありません。」
アンディトーマス

2
@BenThurley-Javaのinstanceofオペレーターは、ほぼ20年前にリリースされたJava 1.0の一部でした。既存のコードを壊すような方法で動作を変更することはほとんどありませんが、その莫大なコストを上回る利点がない場合はありません。20年前、引数をキャストできる場合はtrueを返したり、null引数の場合は例外をスローしたりするための引数があった可能性があります。ただし、これらの定義では、個別のnullチェックが必要になります。
アンディトーマス

3
@BenThurley-動作は過去と現在のJava仕様によって保証されています。ルークのポイントは、現在の保証された動作を決定する際の実験の制限に対処していると思います。
アンディ・トーマス

267

null参照を最初のオペランドとして使用してをinstanceof返しますfalse


268
(そして今、Googleでこの質問を見つけるのに10秒かかります)
PL_kolek

73

確かに非常に良い質問です。自分で試したところです。

public class IsInstanceOfTest {

    public static void main(final String[] args) {

        String s;

        s = "";

        System.out.println((s instanceof String));
        System.out.println(String.class.isInstance(s));

        s = null;

        System.out.println((s instanceof String));
        System.out.println(String.class.isInstance(s));
    }
}

プリント

true
true
false
false

JLS / 15.20.2。型比較演算子instanceof

実行時に、RelationalExpressionの値instanceoftrueそうではなく、参照をを発生させずにReferenceTypeにキャストできる場合、演算子の結果は次のとおりです。それ以外の場合の結果はです。nullClassCastExceptionfalse

API / Class#isInstance(オブジェクト)

このClassオブジェクトがインターフェースを表す場合、このメソッドはtrue、指定されたObject引数のクラスまたはスーパークラスがこのインターフェースを実装するかどうかを返します。それfalse以外の場合は戻ります。このClassオブジェクトがプリミティブ型を表す場合、このメソッドはを返しますfalse


ややこしい。「文字列s」と表示されているため、sは文字列です。nullであるため、sは文字列ではありません。それで、地獄は何ですか?
Kai Wang

1
@KaiWang sは単なるオブジェクト参照変数です。実際に存在するオブジェクト("")を参照する場合と、nullリテラル参照を参照する場合があります。
ジンクォン・

私はまだ混乱しています。sは現在nullである可能性がありますが、後でStringインスタンスを指すことしかできません。Integerのように指すことはできません。したがって、それはnullであっても、文字列の一種です。あまり意味がありません...
Kai Wang

@KaiWang変数の型と実際のオブジェクトの型を混同しています。変数はインスタンスではありません。それらは実質的に単なるポインタです。 nullどの変数が指しているかに関係なく、文字列データではありません。 たとえばs instanceof String、と同じではありませんfield.getType().equals(String.class)
Matthewが

@KaiWangは、呼び出しs instanceof Stringsが実際の値に置き換えられることを想像する必要が"" instanceof Stringありnull instanceof Stringます。このように考えるのはもっと理にかなっているかもしれません。
TimoTürschmann、2018


16

ちょっと一言

でも戻ります。(((A)null)instanceof A)false


(型キャストnullが意外と思われる場合は、たとえば次のような状況でそれを行わなければならないことがあります。

public class Test
{
  public static void test(A a)
  {
    System.out.println("a instanceof A: " + (a instanceof A));
  }

  public static void test(B b) {
    // Overloaded version. Would cause reference ambiguity (compile error)
    // if Test.test(null) was called without casting.
    // So you need to call Test.test((A)null) or Test.test((B)null).
  }
}

したがって、Test.test((A)null)印刷されますa instanceof A: false。)


PS:採用している場合、これを就職の面接の質問として使用しないでください。:D


7

いいえ。Javaリテラルnullは、クラスのインスタンスではありません。したがって、クラスのインスタンスにすることはできません。instanceof どちらかが返されますfalseまたはtrueそのため<referenceVariable> instanceof <SomeClass>のリターンをfalseするときreferenceVariable値がnullです。


5
その説明は奇妙に循環的に聞こえます...しかし、私はあなたが何を意味するのか知っています:-)
クリス

コメントの@クリスty私はあなたが何を意味するかを得た:)。回答を少し編集しました:)。
開発者MariusŽilėnas2017

1

instanceofオペレータは、明示的な必要はありませんnull、それはスローされませんので、チェックをNullPointerExceptionオペランドがある場合null

実行時instanceofに、関係式の値がtrueでない場合、演算子の結果はtrueでありnull、クラスキャスト例外を発生させることなく、参照を参照型にキャストできます。

オペランドである場合nullinstanceofオペレータに戻りfalse、したがっては、明示的なヌルチェックは必要とされません。

以下の例を考えてみましょう。

public static void main(String[] args) {
         if(lista != null && lista instanceof ArrayList) {                     //Violation
                System.out.println("In if block");
         }
         else {
                System.out.println("In else block");
         }
}

の正しい使い方はinstanceof以下の通りです、

public static void main(String[] args) {
      
         if(lista instanceof ArrayList){                     //Correct way
                  System.out.println("In if block");
         }
            else {
                 System.out.println("In else block");
         }  
}
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.