【问题标题】:Check if a Class Object is subclass of another Class Object in Java检查一个类对象是否是Java中另一个类对象的子类
【发布时间】:2011-06-02 20:12:47
【问题描述】:

我正在使用 Java 的反射 API 并尝试处理一些字段。现在我坚持识别我的字段类型。字符串很简单,只需 myField.getType().equals(String.class)。这同样适用于其他非派生类。但是如何检查派生类?例如。 LinkedList 作为List 的子类。我找不到任何isSubclassOf(...)extends(...) 方法。我需要遍历所有getSuperClass() 并自己找到我的超类吗?

【问题讨论】:

  • LinkedList 不是List 的子类。这是List实现
  • 子类型可能是一个更好的术语

标签: java class reflection


【解决方案1】:

除了@To-kra'sanswer。如果有人不喜欢重复:

    public static boolean isSubClassOf(Class<?> clazz, Class<?> superClass) {
        if(Object.class.equals(superClass)) {
            return true;
        }

        for(; !Object.class.equals(clazz); clazz = clazz.getSuperclass()) {
            if(clazz.getSuperclass().equals(superClass)) {
                return true;
            }
        }

        return false;
    }

注意:为了清楚起见,没有空值检查。

【讨论】:

    【解决方案2】:

    你想要这个方法:

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

    一般情况下,List(上)应替换为superclassmyClass 应替换为subclass

    来自JavaDoc

    确定此Class 对象表示的类或接口是否与指定的Class 参数表示的类或接口相同,或者是其超类或超接口。如果是,则返回true;否则返回false。如果这个Class对象代表一个原始类型,如果指定的Class参数正是这个Class对象,这个方法返回true;否则返回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);
    }
    

    【讨论】:

    • 注意方案:SUPERCLASS.isAssignableFrom(SUBCLASS) 这首先让我感到困惑,尽管考虑到命名实际上很明显。
    • @TrudleR 我同意。像SUPERCLASS.isExtendedBy(SUBCLASS) 这样的东西会更容易理解
    • @SeanPatrickFloyd 实际上isExtendedBy 是一个坏名字,因为CLASS.isAssignableFrom(CLASS) 是真的(因此CLASS.isExtendedBy(CLASS) 也是如此)。这不是我所期望的。
    • @Qw3ry 是的,我假设这也是 Api 作者的想法:-)
    【解决方案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
    

    【讨论】:

      【解决方案4】:

      一种检查Class&lt;?&gt;是否是另一个Class&lt;?&gt;的子类的递归方法...

      @To Kraanswer的改进版:

      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);
          }
      }
      

      【讨论】:

        【解决方案5】:

        这是@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;
            }
        }
        

        【讨论】:

          【解决方案6】:

          这对我有用:

          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;
          }
          

          【讨论】:

          • 效果很好,但您可能必须在 clazz = clazz.getSuperclass() 之后添加一个空检查,以防您遇到没有超类的 java.lang.Object。
          【解决方案7】:

          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);
          

          这将启动 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 将包含一个代表 JFrame 类的 Class 对象。

          当然必须包含所需的导入。

          【讨论】:

            【解决方案8】:

            另一个选项是instanceof:

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

            【讨论】:

            • 好电话 (+1)。然后还有两种机制的结合:Class.isInstance(object)download.oracle.com/javase/6/docs/api/java/lang/…
            • 这意味着您实例化了 Field。但我只想“看看”我的班级及其领域,不想“尝试”。
            • 我看到这个方法比“isAssignableFrom”的方式更清晰更清晰,以防你需要检查一个对象的继承树。
            • 请记住,instanceof 也适用于父母(在本例中为 Number)本身,而不仅仅是儿童
            猜你喜欢
            • 2012-05-07
            • 1970-01-01
            • 2023-01-13
            • 2010-10-21
            • 2011-04-25
            • 2018-09-10
            • 1970-01-01
            • 1970-01-01
            • 2021-08-17
            相关资源
            最近更新 更多