Java 是否有可能获得一个类的所有子类?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/1087401/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-11 23:29:47  来源:igfitidea点击:

Is it possible to get all the subclasses of a class?

javareflectionruntime

提问by Chris Wilson

Possible Duplicate:
How do you find all subclasses of a given class in Java?

可能的重复:
你如何在 Java 中找到给定类的所有子类?

Hi,

你好,

I would like to get a list of classes that implement an interface in Java at runtime so I can do a lookup service without having to hard code it. Is there a simple way of doing this? I fear not.

我想获得在运行时用 Java 实现接口的类的列表,以便我可以执行查找服务而无需对其进行硬编码。有没有一种简单的方法可以做到这一点?我怕不是。

采纳答案by cletus

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.

您不能在运行时执行此操作,但在加载类之前无法找到类,您怎么知道它们已加载?您可以扫描每个 JAR 和类文件,但这不是确定的。另外还有诸如 URL 类加载器之类的东西。

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.

您还必须考虑,如果一个类有子类,则可以在以后创建新的子类。

回答by flybywire

If you only load classes from the disk or from URLs then you can scan the classpath and find subclasses "manually".

如果您只从磁盘或 URL 加载类,那么您可以扫描类路径并“手动”查找子类。

回答by uriDium

I am trying to reason through the answer here so I am probably wrong. It would not make sense for a class to have information about its descendants or subclasses because at any point in time someone can create a new subclass of your class. Then you would have to recompile your class to include this new information every time. This does not make sense for extendable code. It is more likely for a class to contain information about its ancestors. So the only solution that I can see is for you to iterate over every class in your problem space and check but this is more than likely a horrible solution for you.

我试图通过这里的答案进行推理,所以我可能错了。一个类拥有关于它的后代或子类的信息是没有意义的,因为在任何时候有人都可以为你的类创建一个新的子类。然后,您每次都必须重新编译您的类以包含这些新信息。这对于可扩展代码没有意义。一个类更有可能包含有关其祖先的信息。因此,我能看到的唯一解决方案是让您遍历问题空间中的每个类并进行检查,但这对您来说很可能是一个可怕的解决方案。

回答by Tim H

I can always create a new subclass for any non-final class, add the subclass to the classpath, and defeat your intent. Subclassing is an open-ended proposition.

我总是可以为任何非最终类创建一个新的子类,将子类添加到类路径中,然后挫败你的意图。子类化是一个开放式命题。

About the best you can do is say that for a given classpath, you know what the subclasses are, and to do that, you'd have to scan each class in the classpath.

关于您能做的最好的事情是说对于给定的类路径,您知道子类是什么,为此,您必须扫描类路径中的每个类。

回答by Amir Afghani

It's fairly simple using reflection. Read this article from JavaWorld

使用反射相当简单。从 JavaWorld 阅读这篇文章

http://www.javaworld.com/javaworld/javatips/jw-javatip113.html

http://www.javaworld.com/javaworld/javatips/jw-javatip113.html

回答by Nick Holt

The only way you'd be able to do it is walking the package hierarchy for the packages available in the classpath checking each class via reflection (and that's gonna suck because you'll effectively load every class, unless you restrict your search to certain packages).

您能够做到这一点的唯一方法是遍历类路径中可用包的包层次结构,通过反射检查每个类(这会很糟糕,因为您将有效地加载每个类,除非您将搜索限制为某些包)。

The trouble with this sort of auto-magical behavior is that it becomes hard to quantify the application without running it, which is a maintenance headache. I'd always prefer to go the injection route (a-la Spring) passing instances via some sort of configuration.

这种自动神奇行为的问题在于,在不运行应用程序的情况下很难量化应用程序,这是一个维护难题。我总是更喜欢通过某种配置来传递实例的注入路线(a-la Spring)。

回答by Nick Holt

Do you want to enumerate classes that implement a particular interface or enumerate classes that derive from some base class? These are two different issues. Both as far as I know would be hard to implement since new implementations can be created/installed on a PC at any time in the future. It sounds like you are trying to create a factory method to instantiate a particular instance and you don't want to hard-code the class name in the code. Usually using a config file that enumerates all the classes that implement the interface is the way to go (or a database can be used). As new classes implement the interface, you add them to the config file and the factory should pick up the new class name.

您想枚举实现特定接口的类还是枚举从某个基类派生的类?这是两个不同的问题。据我所知,这两者都很难实现,因为将来可以随时在 PC 上创建/安装新的实现。听起来您正在尝试创建一个工厂方法来实例化特定实例,并且您不想在代码中对类名进行硬编码。通常使用枚举实现接口的所有类的配置文件是要走的路(或者可以使用数据库)。当新类实现接口时,您将它们添加到配置文件中,工厂应该选择新的类名。

回答by dfa

you should use Java ServiceLoaderthat is a builtin class. It is capable of iterating at runtime over all know service (interface) implementations.

您应该使用内置类的Java ServiceLoader。它能够在运行时迭代所有已知的服务(接口)实现。

If for some reason you don't want it, you can use ClassLoader.getSystemResources() to iterate over all resources; e.g. if you have 6 times the file /META-INF/com.interface you'll get 6 iterations.

如果由于某种原因你不想要它,你可以使用 ClassLoader.getSystemResources() 来遍历所有资源;例如,如果您有 6 次 /META-INF/com.interface 文件,您将获得 6 次迭代。