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

krt*_*tek 23 java oop static design-patterns dynamic-linking

介绍

作为一个免责声明,我读过为什么静态方法不能在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";
}
Run Code Online (Sandbox Code Playgroud)

Oli*_*ire 21

您应该使用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.
  }
}
Run Code Online (Sandbox Code Playgroud)

在注释处理中,您应该检查是否设置了注释,值是否正确,并使编译失败.

软件包的javax.annotation.processing文档中提供了完整的文档.

此外,如果您搜索"java注释处理",则可以在Internet上找到一些教程.

我不会深入研究这个主题,因为我之前从未使用过这项技术.