クラスオブジェクトがJavaの別のクラスオブジェクトのサブクラスであるかどうかを確認する


196

JavaのリフレクションAPIをいじって、いくつかのフィールドを処理しようとしています。今、私は自分のフィールドのタイプを特定することにこだわっています。文字列は簡単ですmyField.getType().equals(String.class)。同じことが他の非派生クラスにも当てはまります。しかし、どのようにして派生クラスをチェックしますか?たとえばのLinkedListサブクラスとしてListisSubclassOf(...)またはextends(...)メソッドが見つかりません。すべてgetSuperClass()を調べて自分のスーパークラスを見つける必要がありますか?


11
LinkedListはのサブクラスではありませんList。これはの実装ですList
TJクラウダー2011年

2
サブタイプの方が適切な用語かもしれません
jpaugh

回答:


402

このメソッドが必要です:

boolean isList = List.class.isAssignableFrom(myClass);

一般的に、ここで、List(上記)と交換しなければならないsuperclassmyClass置き換える必要がありますsubclass

JavaDocから:

このClassオブジェクトによって表されるクラスまたはインターフェースが、指定されたClassパラメーターによって表されるクラスまたはインターフェースと同じか、スーパークラスまたはスーパーインターフェースであるかを決定します。trueそうであれば戻ります。それ以外の場合はを返しますfalse。このClassオブジェクトがプリミティブ型を表す場合、このメソッドはtrue、指定されたClassパラメーターが正確にこのClassオブジェクトであるかどうかを返します。それ以外の場合はを返しますfalse

参照:


関連:

a)オブジェクトが、コンパイル時にわかっているクラスまたはインターフェース(サブクラスを含む)のインスタンスであるかどうかを確認します。

boolean isInstance = someObject instanceof SomeTypeOrInterface;

例:

assertTrue(Arrays.asList("a", "b", "c") instanceof List<?>);

b)オブジェクトが実行時にのみ知っているクラスまたはインターフェース(サブクラスを含む)のインスタンスであるかどうかを確認します。

Class<?> typeOrInterface = // acquire class somehow
boolean isInstance = typeOrInterface.isInstance(someObject);

例:

public boolean checkForType(Object candidate, Class<?> type){
    return type.isInstance(candidate);
}

20
スキームに注意してください。SUPERCLASS.isAssignableFrom(SUBCLASS)これは最初に混乱しましたが、実際には命名を考えれば明らかです。
codepleb

7
@TrudleR同意する。何かSUPERCLASS.isExtendedBy(SUBCLASS)がはるかに理解しやすいでしょう
ショーンパトリックフロイド

@SeanPatrickFloyd isExtendedByは、実際にはCLASS.isAssignableFrom(CLASS)(したがってCLASS.isExtendedBy(CLASS)、同様に)悪い名前です。これは私が期待したものではありません。
Qw3ry 2017年

@ Qw3ryはい、私はそれがApiの作者の考えでもあったと思います:-)
ショーンパトリックフロイド

24

別のオプションはinstanceofです。

Object o =...
if (o instanceof Number) {
  double d = ((Number)o).doubleValue(); //this cast is safe
}

良い電話(+1)。そして、2つのメカニズムの組み合わせもありClass.isInstance(object) ます
Sean Patrick Floyd

5
これは、あなたがそれをインスタンス化することを意味しますField。しかし、私は自分のクラスとそのフィールドを「見たい」だけであり、「それらを試してみる」必要はありません。
craesh

オブジェクトの継承ツリーをチェックする必要がある場合、このメソッドは "isAssignableFrom"の方法よりもはるかに明確で明確です。
cbuchart 2014

それは子供だけでなくinstanceof親(この場合Number)自体にも有効であることを覚えておいてください
lukaszrys

9

instanceofはインスタンス、つまりオブジェクトに対して機能します。クラスを直接操作したい場合があります。この場合、ClassクラスのasSubClassメソッドを使用できます。いくつかの例:

1)

    Class o=Object.class;
    Class c=Class.forName("javax.swing.JFrame").asSubclass(o);

JFrameはObjectのサブクラスなので、これはスムーズに進みます。cには、JFrameクラスを表すClassオブジェクトが含まれます。

2)

    Class o=JButton.class;
    Class c=Class.forName("javax.swing.JFrame").asSubclass(o);

JFrameはJButtonのサブクラスではないため、これはjava.lang.ClassCastExceptionを起動します。cは初期化されません。

3)

    Class o=Serializable.class;
    Class c=Class.forName("javax.swing.JFrame").asSubclass(o);

JFrameはjava.io.Serializableインターフェースを実装しているため、これはスムーズに進みます。cには、JFrameクラスを表すClassオブジェクトが含まれます。

もちろん、必要なインポートを含める必要があります。


5

これは私にとってはうまくいきます:

protected boolean isTypeOf(String myClass, Class<?> superClass) {
    boolean isSubclassOf = false;
    try {
        Class<?> clazz = Class.forName(myClass);
        if (!clazz.equals(superClass)) {
            clazz = clazz.getSuperclass();
            isSubclassOf = isTypeOf(clazz.getName(), superClass);
        } else {
            isSubclassOf = true;
        }

    } catch(ClassNotFoundException e) {
        /* Ignore */
    }
    return isSubclassOf;
}

1
うまく機能しますが、スーパークラスを持たないjava.lang.Objectをヒットした場合に備えて、clazz = clazz.getSuperclass()の後にnullチェックを追加する必要がある場合があります。
Jonas Pedersen 2016年

4

これは、@ schuttekの回答の改良版です。プリミティブに対して正しくfalseを返すため(たとえば、isSubclassOf(int.class、Object.class)=> false)、インターフェイスを正しく処理する(たとえば、isSubclassOf(HashMap.class、Map.class)=> true)ため、改善されています。

static public boolean isSubclassOf(final Class<?> clazz, final Class<?> possibleSuperClass)
{
    if (clazz == null || possibleSuperClass == null)
    {
        return false;
    }
    else if (clazz.equals(possibleSuperClass))
    {
        return true;
    }
    else
    {
        final boolean isSubclass = isSubclassOf(clazz.getSuperclass(), possibleSuperClass);

        if (!isSubclass && clazz.getInterfaces() != null)
        {
            for (final Class<?> inter : clazz.getInterfaces())
            {
                if (isSubclassOf(inter, possibleSuperClass))
                {
                    return true;
                }
            }
        }

        return isSubclass;
    }
}

3

a Class<?>が別のサブクラスであるかどうかを確認する再帰的なメソッドClass<?>...

@To Kra回答の改良版:

protected boolean isSubclassOf(Class<?> clazz, Class<?> superClass) {
    if (superClass.equals(Object.class)) {
        // Every class is an Object.
        return true;
    }
    if (clazz.equals(superClass)) {
        return true;
    } else {
        clazz = clazz.getSuperclass();
        // every class is Object, but superClass is below Object
        if (clazz.equals(Object.class)) {
            // we've reached the top of the hierarchy, but superClass couldn't be found.
            return false;
        }
        // try the next level up the hierarchy.
        return isSubclassOf(clazz, superClass);
    }
}

3

//継承

    class A {
      int i = 10;
      public String getVal() {
        return "I'm 'A'";
      }
    }

    class B extends A {
      int j = 20;
      public String getVal() {
        return "I'm 'B'";
      }
    }

    class C extends B {
        int k = 30;
        public String getVal() {
          return "I'm 'C'";
        }
    }

//メソッド

    public static boolean isInheritedClass(Object parent, Object child) {
      if (parent == null || child == null) {
        return false;
      } else {
        return isInheritedClass(parent.getClass(), child.getClass());
      }
    }

    public static boolean isInheritedClass(Class<?> parent, Class<?> child) {
      if (parent == null || child == null) {
        return false;
      } else {
        if (parent.isAssignableFrom(child)) {
          // is child or same class
          return parent.isAssignableFrom(child.getSuperclass());
        } else {
          return false;
        }
      }
    }

//コードをテストします

    System.out.println("isInheritedClass(new A(), new B()):" + isInheritedClass(new A(), new B()));
    System.out.println("isInheritedClass(new A(), new C()):" + isInheritedClass(new A(), new C()));
    System.out.println("isInheritedClass(new A(), new A()):" + isInheritedClass(new A(), new A()));
    System.out.println("isInheritedClass(new B(), new A()):" + isInheritedClass(new B(), new A()));


    System.out.println("isInheritedClass(A.class, B.class):" + isInheritedClass(A.class, B.class));
    System.out.println("isInheritedClass(A.class, C.class):" + isInheritedClass(A.class, C.class));
    System.out.println("isInheritedClass(A.class, A.class):" + isInheritedClass(A.class, A.class));
    System.out.println("isInheritedClass(B.class, A.class):" + isInheritedClass(B.class, A.class));

//結果

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