具有来自数据库的常量和动态值的枚举
Enum with constant and also dynamic values from database
我的当前状态是 enum
MyType 表示类型 table,列为:
ID
Name
并且它用于通过byId
方法使用ID参数来识别类型:
public enum MyType {
FIRST_TYPE("First Type", 10),
SECOND_TYPE("Second Type", 20);
public static class Holder {
static Map<Integer, MyType > idMap = new HashMap<>();
private Holder() { }
}
private MyType(String name, Integer id) {
this.name = name;
this.id = id;
Holder.idMap.put(id, this);
}
public String getName() {
return name;
}
public static MyType byId(Integer id) {
return Holder.idMap.get(id);
}
我的新要求是支持类型 table 中存在的值,我发现 answers 用于动态枚举,但接受的答案是不这样做
No. Enums are always fixed at compile-time. The only way you could do this would be to dyamically generate the relevant bytecode.
对于同时从数据库(例如 ID 30)中查找 值(主要是 ID),什么是更好的解决方案
select ID from TYPE
我可以扩展现有状态而不是改变它吗?我可以使用方法从数据库添加额外的 IDS 吗?
编辑
即使我按照@StefanFischer 建议的界面进行更新,该界面使用枚举 class 和新数据库 class 填充地图,我仍然希望在代码中使用 [=15] 的枚举 return =] 方法,
public interface MyType {
public static class Holder {
static Map<Integer, MyType> idMap = new HashMap<>();
private Holder() { }
}
public default void add(MyType myType, Integer id) {
Holder.idMap.put(id, myType);
}
public static MyType byId(Integer id) {
return Holder.idMap.get(id);
}
}
如果我理解正确的话,要求是:
- 有一个 MyType.byId(Integer id) 方法可以提供一些预定义的值
- 它也应该从数据库Table
Type
动态扩展
所以枚举不能动态扩展,但我们可以切换到 class。
因此,靠近您的代码可以编写如下内容:
import java.util.HashMap;
import java.util.Map;
public class MyType {
static Map<Integer, MyType> idMap = new HashMap<>();
static {
idMap.put(10, new MyType("First Type"));
idMap.put(20, new MyType("Second Type"));
}
private final String name;
private MyType(String name) {
this.name = name;
}
public String getName() {
return name;
}
public static MyType byId(Integer id) {
return idMap.get(id);
}
public static void addType(String name, Integer id) {
MyType lookup = byId(id);
if(lookup != null) {
if(!lookup.getName().equals(name)) {
System.out.println("conflicting redefinition for id " + id + ": '" + name + "' vs '" + lookup.name + "'");
//handle...
}
}
idMap.put(id, new MyType(name));
}
}
测试数据
假设数据库中有以下内容:
stephan=# select * from Type;
id | name
----+-------------
30 | Third Type
10 | First Type
20 | Second Type
(3 rows)
所以在数据库中我们有 id=10 和 id=20 的预定义类型,还有一个 id=30 的类型,默认情况下应用程序不知道。但是我们可以从数据库中填充类型。
测试用例
public static void main(String[] args) {
try {
Connection connection = createConnection();
try (connection) {
populateTypes(connection);
}
MyType type;
type = MyType.byId(10);
System.out.println(type.getName());
type = MyType.byId(20);
System.out.println(type.getName());
type = MyType.byId(30);
System.out.println(type.getName());
} catch (Exception e) {
e.printStackTrace();
}
}
JDBC 例子
使用什么实际数据库技术来检索值并不重要。这是 JDBC 的示例:
private static void populateTypes(Connection connection)
throws SQLException {
String sql = "SELECT * FROM type";
try (Statement st = connection.createStatement()) {
try (ResultSet rs = st.executeQuery(sql)) {
while (rs.next()) {
int id = rs.getInt("id");
String name = rs.getString("name");
MyType.addType(name, id);
}
}
}
}
演示输出
First Type
Second Type
Third Type
这是你要找的吗?
enum 表示一组常量(不可更改的变量,如 final 变量)。你不能在运行时定义它。
一个明显的non-answer:你试图强迫自己进入错误的兔子洞。
枚举的整体点是在编译时为您提供某些优势。在运行时,如果您有一个 class 和一些 final static Whatever
字段,或者一个具有不同常量的枚举,对 JVM 来说真的无关紧要。或者,如果您使用 EnumSet
而不是普通的 Set
.
您使用枚举是因为它们允许您以更优雅的方式写下您的源代码代码。
因此,在运行时 生成 枚举的方法没有意义。
枚举的想法是您使用它们编写 source 代码。但是当你的枚举被生成给你时,你将如何编写利用它们的源代码?!如前所述,枚举 classes 默认是最终的。您不能单独扩展或增强它们。无论你想要什么,它都需要为你生成。这又提出了一个问题:你如何在编译时利用一些在运行时生成的东西?
因此,从概念的角度来看,另一个答案中概述的方法(使用地图)比尝试将枚举变成某种东西要好得多他们本不应如此。
我的当前状态是 enum
MyType 表示类型 table,列为:
ID
Name
并且它用于通过byId
方法使用ID参数来识别类型:
public enum MyType {
FIRST_TYPE("First Type", 10),
SECOND_TYPE("Second Type", 20);
public static class Holder {
static Map<Integer, MyType > idMap = new HashMap<>();
private Holder() { }
}
private MyType(String name, Integer id) {
this.name = name;
this.id = id;
Holder.idMap.put(id, this);
}
public String getName() {
return name;
}
public static MyType byId(Integer id) {
return Holder.idMap.get(id);
}
我的新要求是支持类型 table 中存在的值,我发现 answers 用于动态枚举,但接受的答案是不这样做
No. Enums are always fixed at compile-time. The only way you could do this would be to dyamically generate the relevant bytecode.
对于同时从数据库(例如 ID 30)中查找 值(主要是 ID),什么是更好的解决方案
select ID from TYPE
我可以扩展现有状态而不是改变它吗?我可以使用方法从数据库添加额外的 IDS 吗?
编辑
即使我按照@StefanFischer 建议的界面进行更新,该界面使用枚举 class 和新数据库 class 填充地图,我仍然希望在代码中使用 [=15] 的枚举 return =] 方法,
public interface MyType {
public static class Holder {
static Map<Integer, MyType> idMap = new HashMap<>();
private Holder() { }
}
public default void add(MyType myType, Integer id) {
Holder.idMap.put(id, myType);
}
public static MyType byId(Integer id) {
return Holder.idMap.get(id);
}
}
如果我理解正确的话,要求是:
- 有一个 MyType.byId(Integer id) 方法可以提供一些预定义的值
- 它也应该从数据库Table
Type
动态扩展
所以枚举不能动态扩展,但我们可以切换到 class。
因此,靠近您的代码可以编写如下内容:
import java.util.HashMap;
import java.util.Map;
public class MyType {
static Map<Integer, MyType> idMap = new HashMap<>();
static {
idMap.put(10, new MyType("First Type"));
idMap.put(20, new MyType("Second Type"));
}
private final String name;
private MyType(String name) {
this.name = name;
}
public String getName() {
return name;
}
public static MyType byId(Integer id) {
return idMap.get(id);
}
public static void addType(String name, Integer id) {
MyType lookup = byId(id);
if(lookup != null) {
if(!lookup.getName().equals(name)) {
System.out.println("conflicting redefinition for id " + id + ": '" + name + "' vs '" + lookup.name + "'");
//handle...
}
}
idMap.put(id, new MyType(name));
}
}
测试数据
假设数据库中有以下内容:
stephan=# select * from Type;
id | name
----+-------------
30 | Third Type
10 | First Type
20 | Second Type
(3 rows)
所以在数据库中我们有 id=10 和 id=20 的预定义类型,还有一个 id=30 的类型,默认情况下应用程序不知道。但是我们可以从数据库中填充类型。
测试用例
public static void main(String[] args) {
try {
Connection connection = createConnection();
try (connection) {
populateTypes(connection);
}
MyType type;
type = MyType.byId(10);
System.out.println(type.getName());
type = MyType.byId(20);
System.out.println(type.getName());
type = MyType.byId(30);
System.out.println(type.getName());
} catch (Exception e) {
e.printStackTrace();
}
}
JDBC 例子
使用什么实际数据库技术来检索值并不重要。这是 JDBC 的示例:
private static void populateTypes(Connection connection)
throws SQLException {
String sql = "SELECT * FROM type";
try (Statement st = connection.createStatement()) {
try (ResultSet rs = st.executeQuery(sql)) {
while (rs.next()) {
int id = rs.getInt("id");
String name = rs.getString("name");
MyType.addType(name, id);
}
}
}
}
演示输出
First Type
Second Type
Third Type
这是你要找的吗?
enum 表示一组常量(不可更改的变量,如 final 变量)。你不能在运行时定义它。
一个明显的non-answer:你试图强迫自己进入错误的兔子洞。
枚举的整体点是在编译时为您提供某些优势。在运行时,如果您有一个 class 和一些 final static Whatever
字段,或者一个具有不同常量的枚举,对 JVM 来说真的无关紧要。或者,如果您使用 EnumSet
而不是普通的 Set
.
您使用枚举是因为它们允许您以更优雅的方式写下您的源代码代码。
因此,在运行时 生成 枚举的方法没有意义。
枚举的想法是您使用它们编写 source 代码。但是当你的枚举被生成给你时,你将如何编写利用它们的源代码?!如前所述,枚举 classes 默认是最终的。您不能单独扩展或增强它们。无论你想要什么,它都需要为你生成。这又提出了一个问题:你如何在编译时利用一些在运行时生成的东西?
因此,从概念的角度来看,另一个答案中概述的方法(使用地图)比尝试将枚举变成某种东西要好得多他们本不应如此。