gpt4 book ai didi

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

转载 作者:行者123 更新时间:2023-11-30 09:26:22 25 4
gpt4 key购买 nike

我正在尝试用 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;
}
}

子类看起来像这样:

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() 检查类然后转换类,但我仍然无法访问静态变量。

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

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

  2. 我可以不使用 Class[] 数组,而是使用包含每个类实例的 DataBase[] 数组。但是,我认为实例化每个可用的 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/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com