Finding all classes implementing a specific interface [duplicate]

假装没事ソ 提交于 2019-11-30 02:46:40

I had a similar need where I wanted to make sure that any classes created that implemented a certain interface were always truly serializable. I created a JavaClassFinder which walks through all directories in the classpath, and finds all classes assignable to the interface I cared about. Here is a code snippet:

public <T> List<Class<? extends T>> findAllMatchingTypes(Class<T> toFind) {
    foundClasses = new ArrayList<Class<?>>();
    List<Class<? extends T>> returnedClasses = new ArrayList<Class<? extends T>>();
    this.toFind = toFind;
    walkClassPath();
    for (Class<?> clazz : foundClasses) {
        returnedClasses.add((Class<? extends T>) clazz);
    }
    return returnedClasses;
}

I'm happy to share the code with you if it helps. The only draw back is that this will only handle .class files -- I didn't add the feature to unzip .jars and read class files from there. (But it wouldn't be a huge project to add that.)

UPDATE: I checked my source code for the above, and found it depends on a lot of helper classes in our standard utility library. To make it easier, I zipped up all the code needed, which you can download from JavaClassFinder.zip. This will set up directly in Eclipse, and you can take whatever portions of the code you need.

You will find a JUnit3 test in the project, called JavaClassFinderTest.java, which shows you the features and usage of the JavaClassFinder class. The only external dependency needed to run the Junit test is Junit.

Basic usage of this utility:

    JavaClassFinder classFinder = new JavaClassFinder();
    List<Class<? extends MyTagInterface>> classes = classFinder.findAllMatchingTypes(MyTagInterface.class);

This will give you a List which contains any classes in the classpath which are assignable from the "MyTagInterface.class" (for example). Hope this helps.

Alex Stybaev

You can find an answer here.

I can suggest using org.reflections

enter link description here

Reflections reflections = new Reflections("com.mycompany");    
Set<Class<? extends MyInterface>> classes = reflections.getSubTypesOf(MyInterface.class);
ChrLipp

I think that org.reflections is a proper solution as mentioned by Alex Stybaev, you don't need to reference the classes in a property file.

Another approach (which I would take) is Spring, since I am using Spring anyway for my applications and therefore wouldn't need any additionally dependencies.

You can find hints for solving your problem with Spring (and alternatives in the other comments or answers) here:

In the comments of your question heikkim and polypiel also link to questions with have answers for solving it with Spring:

Probably the best (standard) way to do this by using the Java SPI mechanism, see Javadoc. The inconvenient (which is also a nice feature) is that it expects Jars that define extensions to list them in META-INF/services/your.fully.qualified.Interface.

The only other way I can think of would be to wall through all ClassLoaders in hope you'll be able to list the files in there, load the class files, and see if they implement your interface or not - which is not a nice thing to do.

Jayan

From the answers of Find Java classes implementing an interface, I used http://software.clapper.org/javautil/: Very fast, very useful.

To do so in pure java, the most correct answer is already voted (from sam goldberg apr 10,2012)

However full code of his is unnecessarily complex. I used his idea and pushed ClassFinder there: http://icedtea.classpath.org/hg/icedtea-web/file/0527ad4eb2dd/netx/net/sourceforge/jnlp/controlpanel/ClassFinder.java

Note - this will work in stand alone application (or any application using regular classpath with jars and dirs) not in ServerContainer.

if your app is running in webserver, you need to know location of your war/ear and search there. Or you have to ask your parent classlaoder where it is he getting yours (and other) sources.

Second note - I'm filtering final locations classes to match only netx and icedtea-web as I do not wont dependencies searched. So if you need to include rt.jar please, rmeove thsoe filters. Or remove bootclasspath at all if you on contrary do not need it at all.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!