2010-10-25 48 views
3

我有一個包含接口和幾個類的包,該包中的某些類實現了該接口,在一個不實現該接口的類中,我想編寫一個方法它返回實現該接口的所有類的對象,我不知道實現該接口的類的名稱,我該如何編寫此方法?javareflection返回實現特定接口的類的列表

回答

1

通常在Java反射API中缺少這樣的功能。但是你可以很容易地實現它。

不久,您可以使用systemp屬性java.class.path來獲取所有的classpath元素。使用屬性path.separator分割它。然後迭代結果數組,使用JAR API讀取每個jar文件,實例化每個Class並檢查您的接口是否爲AssignableFrom(theClass)。

這是查找類路徑中可用的所有BSF引擎的代碼片段。我爲我的博客帖子寫了這篇日誌。此代碼有限制:它僅適用於jar文件。我相信這足以解釋這個想法。

private static Map<String, Boolean> getEngines() throws Exception { 
    Map<String, Boolean> result = new HashMap<String, Boolean>(); 
    String[] pathElements = System.getProperty("java.class.path").split(System.getProperty("path.separator")); 
    for (String pathElement : pathElements) { 
     File resource = new File(pathElement); 
     if (!resource.isFile()) { 
      continue; 
     } 
     JarFile jar = new JarFile(resource); 
     for (Enumeration<JarEntry> e = jar.entries(); e.hasMoreElements();) { 
      JarEntry entry = e.nextElement(); 
      if(entry.isDirectory()) { 
       continue; 
      } 
      if(!entry.getName().endsWith("Engine.class")) { 
       continue; 
      } 
      String className = entry.getName().replaceFirst("\\.class$", "").replace('/', '.'); 
      try { 
       if(BSFEngine.class.getName().equals(className)) { 
        continue; 
       } 
       Class<?> clazz = Class.forName(className); 
       if(BSFEngine.class.isAssignableFrom(clazz) && !clazz.equals(BSFEngine.class)) { 
        result.put(className, true); 
       } 
      } catch (NoClassDefFoundError ex) { 
       // ignore... 
       result.put(className, false); 
      } 
     } 
    } 
    return result; 
} 

該方法返回映射,其中引擎類名稱用作鍵,布爾值指示引擎是否可用。如果引擎在類路徑中需要額外的類,則該引擎不可用。

0

如果我正確理解你的問題,你需要一種方法來檢查,列表中的特定類是否實現了一些特定的接口。您可以使用Class.getInterfaces()方法。

如果您在列出特定軟件包中的所有課程時遇到麻煩,可以查看一下,例如,在this question以及此處的更多鏈接。

2

這個問題沒有簡單的解決方案,但我建議您使用reflections庫。

一旦你擁有它,你可以這樣做:

Reflections reflections = new Reflections("my.project.prefix"); 

Set<Class<? extends SomeClassOrInterface>> subTypes = 
    reflections.getSubTypesOf(SomeClassOrInterface.class);