Проверьте, является ли объект класса подклассом другого объекта класса в Java

198

Я играю с API отражения Java и пытаюсь обработать некоторые поля. Теперь я застрял в определении типа моих полей. Струны легко, просто делай myField.getType().equals(String.class). То же самое относится и к другим не производным классам. Но как я могу проверить производные классы? Например, LinkedListкак подкласс List. Я не могу найти ни один isSubclassOf(...)или extends(...)метод. Мне нужно пройти через все getSuperClass()и найти свой суперкласс самостоятельно?

craesh
источник
11
LinkedListне является подкласс List. Это внедрение в List.
TJ Crowder
2
Подтип может быть лучшего термина
jpaugh

Ответы:

404

Вы хотите этот метод:

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

где в общем случае List(выше) следует заменить на superclassи myClassследует заменить наsubclass

Из JavaDoc :

Определяет, является ли класс или интерфейс, представленный этим Classобъектом, тем же или является суперклассом или суперинтерфейсом класса или интерфейса, представленного указанным Classпараметром. Возвращается, trueесли так; в противном случае это возвращается false. Если этот Classобъект представляет примитивный тип, этот метод возвращает значение, trueесли указанный Classпараметр является именно этим Classобъектом; в противном случае это возвращается false.

Ссылка:


Связанный:

a) Проверьте, является ли Object экземпляром класса или интерфейса (включая подклассы), которые вы знаете во время компиляции:

boolean isInstance = someObject instanceof SomeTypeOrInterface;

Пример:

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

б) Проверьте, является ли объект экземпляром класса или интерфейса (включая подклассы), который вы знаете только во время выполнения:

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

Пример:

public boolean checkForType(Object candidate, Class<?> type){
    return type.isInstance(candidate);
}
Шон Патрик Флойд
источник
21
Обратите внимание на схему: SUPERCLASS.isAssignableFrom(SUBCLASS)это сначала смутило меня, хотя на самом деле это очевидно, учитывая наименование.
codepleb
7
@TrudleR Я согласен. Нечто подобное SUPERCLASS.isExtendedBy(SUBCLASS)было бы намного легче понять
Шон Патрик Флойд
@SeanPatrickFloyd на самом деле isExtendedByявляется плохим именем, как CLASS.isAssignableFrom(CLASS)и в действительности (и, следовательно, CLASS.isExtendedBy(CLASS)также). Это было бы не то, что я ожидал.
Qw3ry
@ Qw3ry да, я предполагаю, что это также, как думали авторы Api :-)
Шон Патрик Флойд
25

Другой вариант - instanceof:

Object o =...
if (o instanceof Number) {
  double d = ((Number)o).doubleValue(); //this cast is safe
}
Landei
источник
Хороший звонок (+1). И затем есть также комбинация двух механизмов: Class.isInstance(object) download.oracle.com/javase/6/docs/api/java/lang/…
Шон Патрик Флойд
5
Это будет означать, что вы воплощаете это Field. Но я просто хочу «посмотреть» на мой класс и его поля, не хочу «пробовать их».
Крэш
Я вижу, что этот метод намного чище и понятнее, чем метод isAssignableFrom, в случае, если вам нужно проверить дерево наследования объекта.
cbuchart
Имейте в виду, что это instanceofтакже работает для родителей (в данном случае Number), а не только детей
lukaszrys
9

instanceof работает на экземплярах, т.е. на объектах. Иногда вы хотите работать непосредственно с классами. В этом случае вы можете использовать метод asSubClass класса Class. Некоторые примеры:

1)

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

это пройдет гладко, потому что JFrame является подклассом Object. c будет содержать объект Class, представляющий класс JFrame.

2)

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

это запустит исключение java.lang.ClassCastException потому что JFrame НЕ является подклассом JButton. c не будет инициализирован.

3)

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

это пройдет гладко, потому что JFrame реализует интерфейс java.io.Serializable. c будет содержать объект Class, представляющий класс JFrame.

Конечно, необходимый импорт должен быть включен.

Marco
источник
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
Работает хорошо, но вам может потребоваться добавить нулевую проверку после clazz = clazz.getSuperclass () в случае, если вы нажмете java.lang.Object, у которого нет суперкласса.
Йонас Педерсен
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;
    }
}
user2415587
источник
3

Рекурсивный метод для проверки, Class<?>является ли подкласс другого Class<?>...

Улучшенная версия @To Кра «S ответ :

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);
    }
}
schuttek
источник
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
joseluisbz
источник