【问题标题】:Class.isAssignableFrom gives wrong results in certain situationClass.isAssignableFrom 在某些情况下给出错误的结果
【发布时间】:2014-12-11 10:45:43
【问题描述】:

我真的对这种行为感到困惑。在 JBoss 7 中,我使用 @Entity Annotation 检索所有类,然后我需要找到所有实现接口“BusinessObject”的类。

这是这样做的方法:

     private Set<Class<? extends BusinessObject>> findEntityClasses() {
        //  Alle Klassen holen, die mit "@Entity" annotiert sind. Dabei werden Hibernate- wie auch javax.persistence Annotations genommen
        Reflections reflections = new Reflections("de.something.b4");
        Set<Class<?>> entityClasses = reflections.getTypesAnnotatedWith(Entity.class);

        //Jetzt in das finale Set nur die Klassen kopieren, die von  BusinessObject erben. Weil andere benutzen wir hier nicht!
        Set<Class<? extends BusinessObject>> boClasses = new HashSet<Class<? extends BusinessObject>>();
        try {
          List<Class> l = new ArrayList<Class>(entityClasses);

          for (Class currentClass : l) {
            //Class newCurrentClass = Class.forName(currentClass.getName());
            if (BusinessObject.class.isAssignableFrom(currentClass)) {
              boClasses.add(currentClass);
            }

          }
        } catch (Throwable t) {
          System.out.println(t.getMessage());
        }

        return boClasses;
      }

请注意 Class.forName() 的注释行!

使用这个注释掉,即使 currentClass 没有实现 BusinessObject,isAssignableFrom always 也会返回 true。

只要我删除 Class.forName() 上的注释,一旦调用它,这个类就会发生一些事情,因此所有后续调用 isAssignableFrom 都会按预期返回正确的值。

我确定这是有原因的,Class.forName() 对类或类加载器做了一些事情,但我不知道是什么。有人知道这种行为吗?

【问题讨论】:

  • 尝试使用 Class.forName( currentClass.getName(), false, this.getClass().getClassloader() ),看看是否仍然会导致问题。
  • 这是一个非常有趣的问题。使用Class.forName 时,请记住它还完全初始化了一个类。所以,@Smith_61 的评论可能会引向正确的方向。
  • @Seelenvirtuose 这是我的想法。反射在未初始化的类对象中返回,并且 JVM 错误在此上下文中使用时无法初始化类。您使用的是什么 JVM/操作系统?我无法在 JVM 8、Windows 8.1 x64 上复制。
  • 感谢您的回复和抱歉 - 之前发布的代码即使 with Class.forName() 也不起作用 - 我将其剥离了一点以美化,但可能有一些东西丢失了。我用我的实际代码编辑了原始帖子。有了这个,我可以重现行为。我已经尝试过初始化 false,但即使是 false - 在调用 Class.forName() 之后一切都按预期工作。另外——如果有趣的话——BusinessObject 类和此代码驻留在部署在耳朵中的不同 jar 中。
  • @philli 您的操作系统/JVM 信息是什么?

标签: java class reflection classloader


【解决方案1】:

引用javadocClass.forName()

forName("X") 的调用会导致初始化名为X 的类。

因此,如果您取消注释 Class.forName(currentClass.getName());,它将初始化类,因此 Class.isAssignableFrom() 将能够正确测试 BusinessObject 是否由类实现(Reflections 可能不会初始化它们)。

【讨论】:

  • 他仍在使用同一个 Class 对象,而不是从 Class.forName() 返回的那个
  • @Smith_61 是的,你是对的,那么可能它只是另一个引用的 javadoc 部分:“导致名为 X 的类被初始化”。
  • 这是我的想法,但我无法在所有已安装的 JVM 上复制它。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-08-09
  • 1970-01-01
  • 1970-01-01
  • 2014-07-16
相关资源
最近更新 更多