在 Java 中模拟静态方法调用的静态抽象和动态链接

介绍

作为免责声明,我读了为什么静态方法不能在Java中抽象,即使我尊重地不同意关于“逻辑矛盾”的公认答案,我也不希望任何关于我的问题的答案的有用性的答案;)static abstract

我有一个类层次结构,表示数据库中的一些表。每个类都继承了包含许多实用程序方法的类,用于访问数据库,创建查询,转义字符等。Entity

类的每个实例都是数据库中的一行。

问题

现在,为了分解尽可能多的代码,我想为每个类添加有关相关列和表名的信息。这些信息必须在没有类实例的情况下可访问,并将用于构建查询等。Entity

存储这些数据的明显方法是每个类中的静态方法返回的静态字段。问题是你不能强迫类实现这些静态方法,也不能在Java中对静态方法调用进行动态链接。

我的解决方案

  1. 使用 或任何类似的数据结构来保存信息。问题 :如果缺少信息,错误将在运行时不编译。HashMap
  2. 对实用程序函数使用并行类层次结构,其中可以实例化每个相应的类并使用动态链接。问题:代码繁重,如果类不存在,则运行时出错

问题

您将如何应对抽象方法上的缺失和动态链接?abstract static

在理想情况下,如果缺少类的信息,并且使用 Entity 类可以轻松访问数据,则给定的解决方案应生成编译错误。

答案不需要在Java中,C#也可以,任何关于如何在没有任何语言的特定代码的情况下做到这一点的见解都将受到欢迎。

需要明确的是,除了简单之外,我没有任何要求。没有什么是静态的。我只想从中检索表和列名称以构建查询。Entity

一些代码

class Entity {
    public static function afunction(Class clazz) { // this parameter is an option
        // here I need to have access to table name of any children of Entity
    }
}

class A extends Entity {
    static String table = "a";
}

class B extends Entity {
    static String table = "b";
}

答案 1

您应该将Java注释与javac注释处理器结合使用,因为它是最有效的解决方案。然而,它比通常的注释范式要复杂一些。

此链接说明如何实现将在编译时使用的注释处理器。

如果我重用你的例子,我会这样:

@Target(ElementType.TYPE)
@Retention(RetentionType.SOURCE)
@interface MetaData {
  String table();
}

abstract class Entity {}

@MetaData(table="a")
class A extends Entity {}

@MetaData(table="b")
class B extends Entity {}

class EntityGetter {
  public <E extends Entity> E getEntity(Class<E> type) {
    MetaData metaData = type.getAnnotation(MetaData.class);
    if (metaData == null) {
      throw new Error("Should have been compiled with the preprocessor.");
      // Yes, do throw an Error. It's a compile-time error, not a simple exceptional condition.
    }
    String table = metaData.table();
    // do whatever you need.
  }
}

在注释处理中,应检查是否已设置注释,值是否正确,并使编译失败。

完整的文档可在软件包 javax.annotation.processing 的文档中找到。

此外,如果您搜索“java注释处理”,则可以在互联网上找到一些教程。

我不会深入探讨这个问题,因为我以前从未使用过这项技术。


答案 2

我遇到了与您相同的问题,现在使用以下方法。将有关列的元数据存储为批注,并在运行时对其进行分析。将此信息存储在地图中。如果你真的希望出现编译时错误,大多数IDE(例如Eclipse)都支持自定义构建器类型,这些类型可以在构建时验证类。

您还可以使用java附带的编译时注释处理工具,该工具也可以集成到IDE版本中。阅读并尝试一下。