Javaで使用される「instanceof」演算子は何ですか?


163

instanceof演算子は何に使用されますか?私はのようなものを見てきました

if (source instanceof Button) {
    //...
} else {
    //...
}

しかし、それは私には意味がありませんでした。私は研究をしましたが、説明なしの例だけを思いつきました。


38
ここで質問をすることには何の問題もありませんが、Javaを学んでいるなら、本を手に入れたいかもしれません。きちんとしたJavaの本なら、この質問への答えと次の1000冊が出てくるでしょう。
James K. Polk大統領

このようなオペレーターには、多くの特定の用途があります。意味のない例の1つについて説明を求められた場合、これは特定の質問になります。
Raedwald 2013

2
以下の答えは正しいですが、instanceofは10回のうち9回の使い過ぎの演算子であることに注意してください。多態性の適切な使用に置き換えることができます(常にではないが、頻繁に)
Richard Tingle 2013

私はリチャードよりもさらに進んでいきます。私は、instanceofの有効な使用を見たことはありません。これは、設計が不十分なコードをすばやくハッキングする場合にのみ役立ちます。OOPが気に入らない場合は、別の言語で書いてください(たくさんあります)。instanceofに「いいえ」と言ってください!
Scott Biggs 2015年

5
@ScottBiggs instanceofオーバーライドするときの良い代替手段はありますequalsか?
Ben Aaronson、2016

回答:


228

instanceofキーワードは、オブジェクト(インスタンス)が指定されたタイプのサブタイプであるかどうかをテストするために使用される2項演算子です。

想像してみてください:

interface Domestic {}
class Animal {}
class Dog extends Animal implements Domestic {}
class Cat extends Animal implements Domestic {}

で作成されたdog オブジェクトを想像してくださいObject dog = new Dog()

dog instanceof Domestic // true - Dog implements Domestic
dog instanceof Animal   // true - Dog extends Animal
dog instanceof Dog      // true - Dog is Dog
dog instanceof Object   // true - Object is the parent type of all objects

しかし、とObject animal = new Animal();

animal instanceof Dog // false

なぜならAnimal、スーパータイプでDogあり、おそらく「洗練されていない」からです。

そして、

dog instanceof Cat // does not even compile!

これはDogがのサブタイプでもスーパータイプでCatもないためであり、実装もしていません。

dog上記で使用されている変数は型であることに注意してくださいObject。これはinstanceof実行時の操作であることを示し、使用例を示します実行時のオブジェクトタイプに基づいて異なる方法で反応します

注意事項:expressionThatIsNull instanceof TすべてのタイプでfalseですT

ハッピーコーディング。


14
試したところ- Object dog = new Dog(); System.out.println(dog instanceof Cat);。これはうまくコンパイルして印刷しfalseます。コンパイラーは、コンパイル時にdog猫ではないことを(JLSの規則に従って)判別することを許可されていません
Erwin Bolwidt

@ErwinBolwidtあなたはそれをしようとしたときにあなたがミスをしました。疑問に思う方のために:JLSセクション15.20.2はあなたが探しているものです。最小限の非稼働例の場合:boolean b = "foo" instanceof Integer;
Felix S

3
@FelixSもう一度答えを読む必要があります。答えは約Object indirect = ...; if (indirect instanceof Something)です。if (literal instanceof Something)想定しているようではありません。
Erwin Bolwidt 2017

1
@ErwinBolwidtああ、そうです、私はそのObject dog部分をスキップしたに違いありません。悪い!
Felix S

dog instanceof Cat // does not even compile!(それがクラスであるため)。Catインターフェースの場合、コンパイルされます。
Hamza Belmellouki

44

式の左側が右側のクラス名のインスタンスである場合に trueを返すのは演算子です。

このように考えてください。あなたの街区にあるすべての家が同じ設計図から建てられたとしましょう。10の家(オブジェクト)、1セットの設計図(クラス定義)。

instanceofオブジェクトのコレクションがあり、それらが何であるかわからない場合に便利なツールです。フォームにコントロールのコレクションがあるとしましょう。そこにあるすべてのチェックボックスのチェック状態を読み取りたいが、チェックされた状態を古いオブジェクトに要求することはできません。代わりに、各オブジェクトがチェックボックスかどうかを確認し、チェックボックスにキャストして、そのプロパティを確認します。

if (obj instanceof Checkbox)
{
    Checkbox cb = (Checkbox)obj;
    boolean state = cb.getState();
}

15
つまり、を使用すると、instanceofダウンキャストを安全に行うことができます。
Raedwald 2013

29

このサイトで説明されているように

instanceofオブジェクトが特定のタイプである場合、オペレータは、テストに使用することができ...

if (objectReference instanceof type)

簡単な例:

String s = "Hello World!"
return s instanceof String;
//result --> true

ただし、instanceofnull参照変数/式に適用するとfalseが返されます。

String s = null;
return s instanceof String;
//result --> false

サブクラスはスーパークラスの「タイプ」なので、これを使用しinstanceofてこれを確認できます ...

class Parent {
    public Parent() {}
}

class Child extends Parent {
    public Child() {
        super();
    }
}

public class Main {
    public static void main(String[] args) {
        Child child = new Child();
        System.out.println( child instanceof Parent );
    }
}
//result --> true

これが役に立てば幸いです!


15

この演算子を使用すると、オブジェクトのタイプを判別できます。boolean値を返します。

例えば

package test;

import java.util.Date;
import java.util.Map;
import java.util.HashMap;

public class instanceoftest
{
    public static void main(String args[])
    {
        Map m=new HashMap();
        System.out.println("Returns a boolean value "+(m instanceof Map));
        System.out.println("Returns a boolean value "+(m instanceof HashMap));
        System.out.println("Returns a boolean value "+(m instanceof Object));
        System.out.println("Returns a boolean value "+(m instanceof Date));
    }
} 

出力は次のとおりです。

Returns a boolean value true
Returns a boolean value true
Returns a boolean value true
Returns a boolean value false


4

他の回答で述べたように、の標準的な典型的な使用法はinstanceof、識別子がより具体的なタイプを参照しているかどうかをチェックすることです。例:

Object someobject = ... some code which gets something that might be a button ...
if (someobject instanceof Button) {
    // then if someobject is in fact a button this block gets executed
} else {
    // otherwise execute this block
}

ただし、左側の式のタイプは右側の親タイプなければならないことに注意してください(JLS 15.20.2およびJava Puzzlers、#50、pp114を参照)。たとえば、次はコンパイルに失敗します。

public class Test {
    public static void main(String [] args) {
        System.out.println(new Test() instanceof String); // will fail to compile
    }
}

これは次のメッセージでコンパイルに失敗します:

Test.java:6: error: inconvertible types
        System.out.println(t instanceof String);
                       ^
  required: String
  found:    Test
1 error

Test親クラスではないのでString。OTOH、これは完全にコンパイルfalseされ、期待どおりに印刷されます:

public class Test {
    public static void main(String [] args) {
        Object t = new Test();
        // compiles fine since Object is a parent class to String
        System.out.println(t instanceof String); 
    }
}

仕様にリンクしていただきありがとうございます。
jpaugh、2016年

1
public class Animal{ float age; }

public class Lion extends Animal { int claws;}

public class Jungle {
    public static void main(String args[]) {

        Animal animal = new Animal(); 
        Animal animal2 = new Lion(); 
        Lion lion = new Lion(); 
        Animal animal3 = new Animal(); 
        Lion lion2 = new Animal();   //won't compile (can't reference super class object with sub class reference variable) 

        if(animal instanceof Lion)  //false

        if(animal2 instanceof Lion)  //true

        if(lion insanceof Lion) //true

        if(animal3 instanceof Animal) //true 

    }
}

1

等価性チェックの省略表現として使用できます。

したがって、このコード

if(ob != null && this.getClass() == ob.getClass) {
}

次のように書くことができます

if(ob instanceOf ClassA) {
}

1

ほとんどの人がこの質問の「何を」を正しく説明しましたが、「どのように」を正しく説明した人はいません。

だからここに簡単なイラストがあります:

String s = new String("Hello");
if (s instanceof String) System.out.println("s is instance of String"); // True
if (s instanceof Object) System.out.println("s is instance of Object"); // True
//if (s instanceof StringBuffer) System.out.println("s is instance of StringBuffer"); // Compile error
Object o = (Object)s;
if (o instanceof StringBuffer) System.out.println("o is instance of StringBuffer"); //No error, returns False
else System.out.println("Not an instance of StringBuffer"); // 
if (o instanceof String) System.out.println("o is instance of String"); //True

出力:

s is instance of String
s is instance of Object
Not an instance of StringBuffer
o is instance of String

sStringBufferと比較するときにコンパイラエラーが発生する理由は、ドキュメント詳しく説明されています。

これを使用して、オブジェクトがクラスのインスタンス、サブクラスのインスタンス、または特定のインターフェースを実装するクラスのインスタンスであるかどうかをテストできます。

これは、LHSがRHSまたはRHSを実装または拡張するクラスのインスタンスのいずれかである必要があることを意味します。

次に、instanceofを使用する方法は?
すべてのクラスはオブジェクトを拡張するので、LHSをオブジェクトに型キャストすると、常に有利に機能します。

String s = new String("Hello");
if ((Object)s instanceof StringBuffer) System.out.println("Instance of StringBuffer"); //No compiler error now :)
else System.out.println("Not an instance of StringBuffer");

出力:

Not an instance of StringBuffer

最後の例では、なぜ「StringBufferのインスタンスではない」を返すのですか?LHSでsをObjectに型キャストし、それがRHSのインスタンスであるかどうかをチェックしているif ((Object)s instanceof StringBuffer) System.out.println("Instance of StringBuffer"); //shouldn't this be trueので、sをObjectに型キャストしているので、
sofs1 2018

sはStringオブジェクトへの参照であり(JavaはC ++とは異なり、動的ポリモーフィズムを採用しています)、StringはStringBufferのサブクラスではありません。
sziraqui 2018


0

キーワードのインスタンスは、特定のオブジェクトのインスタンスを知りたい場合に役立ちます。

例外をスローし、キャッチしたときに合計カスタム操作を実行し、ロジック(スローまたはログなど)に従って再び続行するとします

例:1)ユーザーがカスタム例外 "InvalidExtensionsException"を作成し、ロジックに従ってスローしました

2)現在、catchブロックでcatch(例外e){例外タイプが "InvalidExtensionsException"の場合、合計ロジックを実行します

InvalidExtensionsException InvalidException =(InvalidExtensionsException)e;

3)のインスタンスをチェックしておらず、例外タイプがNullポインタ例外の場合、コードは壊れます。

したがって、ロジックはif(e instanceof InvalidExtensionsException){InvalidExtensionsException InvalidException =(InvalidExtensionsException)e;のインスタンス内にある必要があります。}

上記の例は間違ったコーディング方法ですが、この例は、そのインスタンスの使用法を理解するのに役立ちます。


0

一番いい説明はjlsです。常にソースが言っていることを確認してみてください。そこにあなたはベストアンサーとはるかに多くを得るでしょう。ここでいくつかのパーツを複製します:

instanceof演算子のRelationalExpressionオペランドの型は、参照型またはnull型である必要があります。そうしないと、コンパイル時エラーが発生します。

instanceof演算子の後に記述されているReferenceTypeが再参照可能な参照型を示していない場合(4.7節)は、コンパイル時エラーです。

ReferenceTypeへのRelationalExpressionのキャスト(§15.16)がコンパイル時エラーとして拒否される場合、関係式のinstanceofも同様にコンパイル時エラーを生成します。このような状況では、instanceof式の結果が真になることはありません。


0

java instanceof演算子は、オブジェクトが指定されたタイプ(クラスまたはサブクラスまたはインターフェース)のインスタンスであるかどうかをテストするために使用されます。

Javaのinstanceofはcomparison operator、インスタンスとタイプを比較するため、タイプとも呼ばれます。trueまたはを返しますfalse。値instanceofを持つ変数に演算子を適用するとnull、が返されますfalse

JEP 305を含むJDK 14+から、「パターンマッチング」を行うこともできます。instanceof

パターンは基本的に、値が特定のタイプを持っていることをテストし、一致するタイプを持っているときに値から情報を抽出できます。パターンマッチングを使用すると、システム内の一般的なロジックをより明確かつ効率的に表現できます。つまり、オブジェクトからのコンポーネントの条件付き削除です。

Java 14より前

if (obj instanceof String) {
    String str = (String) obj; // need to declare and cast again the object
    .. str.contains(..) ..
}else{
     str = ....
}

Java 14の機能強化

if (!(obj instanceof String str)) {
    .. str.contains(..) .. // no need to declare str object again with casting
} else {
    .. str....
}

型チェックと他の条件を組み合わせることもできます

if (obj instanceof String str && str.length() > 4) {.. str.contains(..) ..}

でパターンマッチングを使用するとinstanceof、Javaプログラムでの明示的なキャストの総数が減ります。

PSinstanceOfオブジェクトがnullでない場合にのみ一致し、オブジェクトにのみ割り当てることができますstr


-1
class Test48{
public static void main (String args[]){
Object Obj=new Hello();
//Hello obj=new Hello;
System.out.println(Obj instanceof String);
System.out.println(Obj instanceof Hello);
System.out.println(Obj instanceof Object);
Hello h=null;
System.out.println(h instanceof Hello);
System.out.println(h instanceof Object);
}
}  

1
StackOverflowで回答のみをコードに投稿しないでください。先に進んで説明を追加してください。
L.ガタール

-2

非常に単純なコード例:

If (object1 instanceof Class1) {
   // do something
} else if (object1 instanceof Class2) {
   // do something different
}

ここで注意してください。上記の例では、Class1がObjectの場合、最初の比較は常にtrueになります。したがって、例外と同様に、階層の順序が重要です!


-2

マップを使用して、インスタンスの高度な抽象化を行うことができます

private final Map<Class, Consumer<String>> actions = new HashMap<>();

次に、そのようなマップにアクションを追加します。

actions.put(String.class, new Consumer<String>() {
        @Override
        public void accept(String s) {
           System.out.println("action for String");       
        }
    };

次に、不明なタイプのオブジェクトがあると、そのマップから特定のアクションを取得できます。

actions.get(someObject).accept(someObject)

-2

instanceof演算子は、オブジェクトが指定されたタイプのインスタンスであるかどうかを確認するために使用されます。(クラスまたはサブクラスまたはインターフェース)。

instanceofは、インスタンスとタイプを比較するため、タイプ比較演算子とも呼ばれます。trueまたはfalseを返します。

class Simple1 {  
public static void main(String args[]) {  
Simple1 s=new Simple1();  
System.out.println(s instanceof Simple1); //true  
}  
}  

null値を持つ変数にinstanceof演算子を適用すると、falseが返されます。

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