在没有实例化的情况下从子类获取数据

时间:2009-03-03 20:07:28

标签: java

我有一个抽象的超类和各种子类。每个子类都包含一个我想静态使用的值,但是不可能创建一个抽象的静态方法。我想动态地从它们获取一个值,而不必创建实例。我该怎么办?

另一个问题是:我如何循环子类?它甚至可能吗?

一次尝试涉及将类名(Subclass.class)映射到该值并尝试对它们使用newInstance,因此我可以使用方法来获取值,但这不起作用。

我的方法在哪里出错?

7 个答案:

答案 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()(可能)将无效,除非:

  • 班级是公开的
  • 构造函数是public
  • 构造函数不带参数

最后一个是强制性的,另外两个取决于你正在做什么包(我想,自从我关心以来已经有一段时间了)。使用Constructor类更好。

您能举出一个简短的代码示例,说明您正在考虑做什么吗?基于此我(和其他人)可能能够给你更好的答案。如果你确实需要做映射子类的事情,我可以挖掘一些代码来实现它......

答案 6 :(得分:0)

为每个子类创建第二个类,表示该子类的类型可能有效。

例如,为每个子类创建一个工厂类(一个负责创建该子类实例的类)。每个工厂类只需要一个实例。

然后,每个工厂类都可以负责了解您描述的子类特定数据。然后,您只需要遍历一组固定的工厂类。