How do you find all subclasses of a given class in Java?
There is no other way to do it other than what you described. Think about it - how can anyone know what classes extend ClassX without scanning each class on the classpath?
Eclipse can only tell you about the super and subclasses in what seems to be an "efficient" amount of time because it already has all of the type data loaded at the point where you press the "Display in Type Hierarchy" button (since it is constantly compiling your classes, knows about everything on the classpath, etc).
Is it possible to get all the subclasses of a class?
The short answer is no.
The long answer is that subclasses can come into existence in many ways, which basically makes it impossible to categorically find them all.
You can't do it at runtime but you can't find classes until they're loaded and how do you know they're loaded? You could scan every JAR and class file but that's not definitive. Plus there are things like URL class loaders.
Inner classes (static and non-static) are another case to consider. Named inner classes are easier to find. Anonymous inner classes are potentially much more difficult to find.
You also have to consider that if a class has subclasses then new subclasses can be created at a later point.
How to find which subclasses of given class implement a particular interface in Eclipse?
You can use the java search in two steps:
Assuming subclasses C1
and C3
of A
implement B
, but C2
does not:
In the first step, select class A
and search for all subclasses of A using the java search (Search->Java...) with option implementors:
Then the search view pops up and we see all subclasses of A:
Select them and hit "Search->Java..." again. Now we can search within this selection for implementors of B
.
This gives us subclasses of A
that implement B
:
find subclasses of a given class in jdk lib
Why do you not try one of the solutions from your link?
Find below a simple example using https://github.com/ronmamo/reflections.git
.
After having a look in the test
classes this example was straight forward.
Reflections reflections = new Reflections(new ConfigurationBuilder()
.setUrls(Arrays.asList(ClasspathHelper.forClass(List.class))));
Set<Class<? extends List>> subTypes = reflections.getSubTypesOf(List.class);
for (Class c : subTypes) {
System.out.println("subType: " + c.getCanonicalName());
}
How to find all the subclasses of a class given its name?
New-style classes (i.e. subclassed from object
, which is the default in Python 3) have a __subclasses__
method which returns the subclasses:
class Foo(object): pass
class Bar(Foo): pass
class Baz(Foo): pass
class Bing(Bar): pass
Here are the names of the subclasses:
print([cls.__name__ for cls in Foo.__subclasses__()])
# ['Bar', 'Baz']
Here are the subclasses themselves:
print(Foo.__subclasses__())
# [<class '__main__.Bar'>, <class '__main__.Baz'>]
Confirmation that the subclasses do indeed list Foo
as their base:
for cls in Foo.__subclasses__():
print(cls.__base__)
# <class '__main__.Foo'>
# <class '__main__.Foo'>
Note if you want subsubclasses, you'll have to recurse:
def all_subclasses(cls):
return set(cls.__subclasses__()).union(
[s for c in cls.__subclasses__() for s in all_subclasses(c)])
print(all_subclasses(Foo))
# {<class '__main__.Bar'>, <class '__main__.Baz'>, <class '__main__.Bing'>}
Note that if the class definition of a subclass hasn't been executed yet - for example, if the subclass's module hasn't been imported yet - then that subclass doesn't exist yet, and __subclasses__
won't find it.
You mentioned "given its name". Since Python classes are first-class objects, you don't need to use a string with the class's name in place of the class or anything like that. You can just use the class directly, and you probably should.
If you do have a string representing the name of a class and you want to find that class's subclasses, then there are two steps: find the class given its name, and then find the subclasses with __subclasses__
as above.
How to find the class from the name depends on where you're expecting to find it. If you're expecting to find it in the same module as the code that's trying to locate the class, then
cls = globals()[name]
would do the job, or in the unlikely case that you're expecting to find it in locals,
cls = locals()[name]
If the class could be in any module, then your name string should contain the fully-qualified name - something like 'pkg.module.Foo'
instead of just 'Foo'
. Use importlib
to load the class's module, then retrieve the corresponding attribute:
import importlib
modname, _, clsname = name.rpartition('.')
mod = importlib.import_module(modname)
cls = getattr(mod, clsname)
However you find the class, cls.__subclasses__()
would then return a list of its subclasses.
Related Topics
Compare Two Objects With .Equals() and == Operator
Capturing Stdout When Calling Runtime.Exec
Java.Net.Socketexception: Connection Reset
Using Threads to Make Database Requests
Maven: Add a Dependency to a Jar by Relative Path
Close a Scanner Linked to System.In
Difference Between a Static and a Non-Static Initialization Code Block
Difference Between Final and Effectively Final
"Expected Begin_Object But Was String At Line 1 Column 1"
What Do 3 Dots Next to a Parameter Type Mean in Java
How to Convert Jsonstring to Jsonobject in Java
What Are the Rules For Evaluation Order in Java
How to Implement a Tree Data-Structure in Java
Recursively List Files in Java
What Do ^ and $ Mean in a Regular Expression