java - 通过访问 Class 对象中的静态变量来确定选择哪个子类

标签 java selection abstract-class subclass static-variables

我正在尝试在 Java 中实现一个接口(interface),以便为一个应用程序使用不同类型的数据库。 我的想法是创建一个具有公共(public)接口(interface)和两个静态变量的抽象类,然后它们被子类覆盖。然后,我想添加一个 Class[] 列表,其中包含抽象类中所有可用子类的类,以及几个允许确定要使用的正确类的函数。

目标是首先获取所有可用数据库类型的列表,然后让用户选择一个。之后另一个函数应该将名称(可以本地化)翻译为 IDENTIFIER这是在子类中指定的。最后,第三个函数允许通过给出这样的 IDENTIFIER 来实例化对象。 .

我的抽象类看起来像这样:

public abstract class DataBase {
    public static final IDENTIFIER = "";
    public static final NAME = "";
    private static final Class[] dbTypes = new Class[]{PostgreSQL.class, MySQL.class};

    public static String[] getNameList() {
        String[] names = new String[dbTypes.length];
        for(int i = 0; i < dbTypes.length; i++){
            names[i] = dbTypes[i].NAME;       //Cannot access the static variable this way.
        }
        return names;
    }
    public static String getIdentifierForName(String name) {
        for(int i = 0; i < dbTypes.length; i++){
            if(name.equals(dbTypes[i].NAME){       
                return dbTypes[i].IDENTIFIER;
            }
        }
        return "";
    }
    public static DataBase getInstanceOf(String identifier) {
        for(int i = 0; i < dbTypes.length; i++){
            if(identifier.equals(dbTypes[i].IDENTIFIER) {       
                return dbTypes[i].newInstance();
            }
        }
        return null;
    }
}

Child 类看起来像这样:

public class MySQL extends DataBase {
    public static final IDENTIFIER = "ab.cde.MySQL";
    public static final NAME = "MySQL";
    ...
}
public class PostgreSQL extends DataBase{
    public static final IDENTIFIER = "ab.cde.PostgreSQL";
    public static final NAME = "PostgreSQL";
    ...
}

我现在的问题是,我无法从 Class 对象访问静态变量。显然 dbTypes 列表不包含任何类型化类。我尝试将数组的类型更改为 Class<? extends DataBase> ,但我收到错误 Cannot create a generic array of Class<? extends DataBase>我还尝试使用 isAssignableFrom() 检查类(class)然后转换类,但我仍然无法访问静态变量。

目前我有两个有效的解决方案:

  1. 将所有现有子类硬编码到每个函数中 if(PostgreSQL.NAME.equals(name)){...} ETC。 但是,如果我添加新的子类,我只想在实现中的某一时刻添加它们。

  2. 我可以使用包含每个类实例的 DataBase[] 数组,而不是使用 Class[] 数组。但是,我认为实例化每个可用的 DataBase 子类是一种不好的做法,即使我最终只需要一个。

由于我以前从未做过这样的事情,所以我可能完全错误地处理了这个问题。也许我错过了通常完成此类事情的正确方法?

感谢您的帮助。

最佳答案

Java 中没有“抽象属性”。您必须在 DataBase 类中创建两个抽象方法,如下所示:

public abstract class DataBase {

    // No "abstract propeties"

    public abstract String getDBName();
    public abstract String getDBIdentifier();

    // etc etc...

}

然后,在每个子类中:

public class MySQL extends DataBase {

    public static final IDENTIFIER = "ab.cde.MySQL";
    public static final NAME = "MySQL";

    @Override
    public String getDBName() {
       return NAME;
    }

    @Override
    public String getDBIdentifier() {
       return IDENTIFIER;
    }

    // etc etc...

}

使用这些类时,您只需转换为DataBase(不是MySQLPostgreSQL)并调用两个抽象方法。

因此,为了解决您的“选择数据库类”问题,我将创建一个包含数据库名称和相应类的配置文件,并通过反射实例化它(newInstance())根据需要。

作为替代方案,您可以使用反射来访问静态变量,如 Nikita 建议的答案,或者您可以使用类的名称作为它支持的数据库的标识符,如下所示(未测试):

public abstract class DataBase {

    private static final Class[] dbTypes = new Class[]{PostgreSQL.class, MySQL.class};

    public static Class getDBClass(String type) {
       for (Class c : dbTypes) {
           if (c.getSimpleName().toLowerCase().equals(type.toLowerCase())) {
               return c;
           }
       }
       return null;
    }

    public static Set<String> getSupportedDB() { // <-- you populate a dropdown menu with this
       Set<String> supported = new HashSet<String>();
       for (Class c : dbTypes) {
           supported.add(c.getSimpleName());
       }
       return supported;
    }

    // etc etc...

}

但是,我不喜欢这个解决方案,也不会使用它。

关于java - 通过访问 Class 对象中的静态变量来确定选择哪个子类,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14954017/

相关文章:

java - 使用 android 从 stripe 生成银行帐户 token

javascript - 每当按下光标或箭头键时,如何获取当前光标位置(在文本区域中)?

algorithm - 部分排序以找到第 k 个最大/最小元素

java - 抽象类中的main方法有什么用?

java - 如何在EXTJS网格中插入数据?

java - @WebMvcTest可以有两个 Controller 吗

javascript - Thymeleaf 对象到 Javascript 对象错误 : TemplateProcessingException

java - Jtree根据鼠标点击获取对象?

c# - 我可以用这种方式为所有派生的单例定义一个抽象类吗?

java - 如何检查抽象对象的实例是否属于特定的子类