我有一个抽象的超类和各种子类。每个子类都包含一个我想静态使用的值,但是不可能创建一个抽象的静态方法。我想动态地从它们获取一个值,而不必创建实例。我该怎么办?
另一个问题是:我如何循环子类?它甚至可能吗?
一次尝试涉及将类名(Subclass.class)映射到该值并尝试对它们使用newInstance,因此我可以使用方法来获取值,但这不起作用。
我的方法在哪里出错?
答案 0 :(得分:1)
为什么不以另一种方式去做呢?把数据放在某个地方可以静态访问,并让子类从那里得到它?
当然,这种可行性取决于数据的性质,但是当你发现自己遇到这种障碍时,往往有助于退后一步并重新审视你的假设。
- MarkusQ
答案 1 :(得分:1)
您可以通过反射引用静态成员/方法,但是没有自动方法来查找类的所有子类。
考虑通过其他一些机制提供子类/实例工厂/元数据类,例如ServiceLoader服务或其他一些插件框架。
答案 2 :(得分:1)
也许你在寻找枚举?
public enum Planet
{
MERCURY (2.4397e6),
VENUS (6.0518e6),
EARTH (6.37814e6);
private final double radius;
Planet(double radius)
{
this.radius = radius;
}
public double radius()
{
return radius;
}
}
您不必自己创建enum
个实例。枚举可以有值,例如示例中为radius()
。您可以向它们添加行为,以便它们可以像普通类一样,通过在它们上定义抽象方法,例如
public enum Planet
{
...
abstract double weightOnSurface(double weight);
...
}
您可以循环访问枚举,如下所示:
for (Planet p : Planet.values())
{
System.out.println(p.radius());
}
所以他们似乎符合你的所有标准。
答案 3 :(得分:0)
如果您有一组固定的子类,那么您可以将数据放在超类中。如果可以添加子类,则无法将它们全部列出。您可以从静态初始化器中获取子类,让超类知道它们的存在(或者使用代理!)。
通常,超类不应该知道它们的子类。但是,您可能想要(或更好地重构)您的超类成为超类型以及其他负责您的子类的类。
答案 4 :(得分:0)
您需要扫描包和clasess以查找扩展超类的内容 - 遗憾的是,这不能通过Reflection API完成,但必须通过URL(文件系统类,jar文件等)完成。在这种情况下,注释的使用可能更好,许多开源产品都使用这种方法(Hibernate等)。
然后你可以在每个(一致的命名或注释)中使用静态方法,你应该能够调用method.invoke(MyObject.class, arguments)
另一种选择是在抽象类中放置一个注册表映射 - 如果你需要强制它,抽象构造函数将获取静态值(或者只在需要计算时存储子类)。如果您正在控制所有子类,只需确保每个子类都有一个静态块即可将其添加到注册表中。
答案 5 :(得分:0)
映射子类......你可以通过反射来实现它(但它不会很有趣)。
newInstance()(可能)将无效,除非:
最后一个是强制性的,另外两个取决于你正在做什么包(我想,自从我关心以来已经有一段时间了)。使用Constructor类更好。
您能举出一个简短的代码示例,说明您正在考虑做什么吗?基于此我(和其他人)可能能够给你更好的答案。如果你确实需要做映射子类的事情,我可以挖掘一些代码来实现它......
答案 6 :(得分:0)
为每个子类创建第二个类,表示该子类的类型可能有效。
例如,为每个子类创建一个工厂类(一个负责创建该子类实例的类)。每个工厂类只需要一个实例。
然后,每个工厂类都可以负责了解您描述的子类特定数据。然后,您只需要遍历一组固定的工厂类。