1. 序章

このクイックチュートリアルでは、Javaの演算子のインスタンスについて学習します。

2. instanceof 演算子とは何ですか?

instanceof is a binary operator we use to test if an object is of a given type. The result of the operation is either true or false. It’s also known as a type comparison operator because it compares the instance with the type.

不明なオブジェクトをキャストする前に、instanceofチェックを常に使用する必要があります。 Doing this helps to avoid a ClassCastException at runtime.

instanceof演算子の基本的な構文は次のとおりです。

(object) instanceof (type)

Now let’s see a basic example for the instanceof operator. First, we’ll create a class Round:

public class Round {
    // implementation details
}

Next, we’ll create a class Ring that extends Round:

public class Ring extends Round {
    // implementation details
}

instanceof を使用して、RingのインスタンスがRoundタイプであるかどうかを確認できます。

@Test
public void givenWhenInstanceIsCorrect_thenReturnTrue() {
    Ring ring = new Ring();
    Assert.assertTrue(ring instanceof Round);
}

3. インスタンスのオペレーターはどのように機能しますか?

instanceof演算子は、is-a関係の原則に基づいて動作します。 is-a関係の概念は、クラス継承またはインターフェースの実装に基づいています。

To demonstrate this, we’ll create a Shape interface:

public interface Shape {
    // implementation details
}

We’ll also create a class Circle, which implements the Shape interface and also extends the Round class:

public class Circle extends Round implements Shape {
    // implementation details
}

オブジェクトが次のタイプのインスタンスである場合、instanceofの結果はtrueになります。

@Test
public void givenWhenObjectIsInstanceOfType_thenReturnTrue() {
    Circle circle = new Circle();
    Assert.assertTrue(circle instanceof Circle);
}

オブジェクトが次のタイプのサブクラスのインスタンスである場合も、trueになります。

@Test
public void giveWhenInstanceIsOfSubtype_thenReturnTrue() {
    Circle circle = new Circle();
    Assert.assertTrue(circle instanceof Round);
}

タイプがインターフェースの場合、オブジェクトがインターフェースを実装すると、trueが返されます。

@Test
public void givenWhenTypeIsInterface_thenReturnTrue() {
    Circle circle = new Circle();
    Assert.assertTrue(circle instanceof Shape);
}

The instanceof operator can’t be used if there’s no relationship between the object that’s being compared and the type it’s being compared with.

We’ll create a new class, Triangle, that implements Shape, but has no relationship with Circle:

public class Triangle implements Shape {
    // implementation details
}

Now if we use instanceof to check if a Circle is an instance of Triangle:

@Test
public void givenWhenComparingClassInDiffHierarchy_thenCompilationError() {
    Circle circle = new Circle();
    Assert.assertFalse(circle instanceof Triangle);
}

We’ll get a compilation error because there’s no relationship between the Circle and Triangle classes:

java.lang.Error: Unresolved compilation problem:
  Incompatible conditional operand types Circle and Triangle

4. Using instanceof With the Object Type

Javaでは、すべてのクラスがObjectクラスから暗黙的に継承します。 したがって、instanceof演算子をObjectタイプで使用すると、常にtrueと評価されます。

@Test
public void givenWhenTypeIsOfObjectType_thenReturnTrue() {
    Thread thread = new Thread();
    Assert.assertTrue(thread instanceof Object);
}

5. オブジェクトがnullの場合に、instanceof演算子を使用する

If we use the instanceof operator on any object that’s null, it returns false. We also don’t need a null check when using an instanceof operator.

@Test
public void givenWhenInstanceValueIsNull_thenReturnFalse() {
    Circle circle = null;
    Assert.assertFalse(circle instanceof Round);
}

6. instanceofおよびGenerics

インスタンスのテストとキャストは、実行時に型情報を検査することに依存しています。 したがって、instanceofを消去されたジェネリック型と一緒に使用することはできません

たとえば、次のスニペットをコンパイルしようとすると、次のようになります。

public static <T> void sort(List<T> collection) {
    if (collection instanceof List<String>) {
        // sort strings differently
    }
        
    // omitted
}

次に、このコンパイルエラーが発生します。

error: illegal generic type for instanceof
        if (collection instanceof List<String>) {
                                      ^

Technically speaking, we’re only allowed to use instanceof along with reified types in Java. A type is reified if its type information is present at runtime.

Javaで修正されたタイプは次のとおりです。

  • Primitive types, like int
  • Non-generic classes and interfaces, like String or Random
  • Generic types in which all types are unbounded wildcards, like Set> or Map, ?>
  • Raw types, like List or HashMap
  • Arrays of other reifiable types, like String[], List[], or Map, ?>[]

ジェネリック型パラメーターは具体化されていないため、次のように使用することもできません。

public static <T> boolean isOfType(Object input) {
    return input instanceof T; // won't compile
}

ただし、次のようなものに対してテストすることは可能ですリスト>

if (collection instanceof List<?>) {
    // do something
}

7. 結論

In this brief article, we learned about the instanceof operator and how to use it. 完全なコードサンプルは、GitHubから入手できます。