Java 如何用基类硬编码静态关系数据?
在我的应用程序中,我需要在运行时访问一些“关系”数据。如果我有很多数据或者经常更改,我会将其存储在DB(sqlite或其他)中。但是我只有几个5-50个对象的实体,它们不会(经常)改变,并且会由开发人员单独改变。因此,我认为简单地在Java类中硬编码数据以实现更简单的代码维护是有意义的 所有实体共享一个公共抽象超类(具有Java 如何用基类硬编码静态关系数据?,java,database,enums,static,hardcode,Java,Database,Enums,Static,Hardcode,在我的应用程序中,我需要在运行时访问一些“关系”数据。如果我有很多数据或者经常更改,我会将其存储在DB(sqlite或其他)中。但是我只有几个5-50个对象的实体,它们不会(经常)改变,并且会由开发人员单独改变。因此,我认为简单地在Java类中硬编码数据以实现更简单的代码维护是有意义的 所有实体共享一个公共抽象超类(具有int-id和字符串名)。 定义数据之后,我希望引用每个实体对象和集合/数组,所有这些对象都可以在类之外使用。 我想确保数据是不可变的 第一个想法是这样做: public abs
int-id
和字符串名
)。
定义数据之后,我希望引用每个实体对象和集合/数组,所有这些对象都可以在类之外使用。
我想确保数据是不可变的
第一个想法是这样做:
public abstract class AbstractEntity{
private final int id;
private String name;
protected AbstractEntity(int id, String name){
this.id = id;
this.name = name;
}
private void someMethods(){
...
}
abstract protected void someAbstractMethods(){
...
}
}
public final class MyEntity extends AbstractEntity{
public static final ENTITY_1 = new MyEntity(1, "Entity 1", "foo");
public static final ENTITY_2 = new MyEntity(2, "Entity 2", "bar");
public static final ENTITY_3 = new MyEntity(3, "Entity 3", "baz");
public static final Set<MyEntity> ALL = Collections.unmodifiableSet(new TreeSet<>(Arrays.asList(ENTITY_1, ENTITY_2, ENTITY_3)));
private final String foo;
private MyEntity(int id, String name, String foo){
super(id, name);
this.foo = foo;
}
}
公共抽象类AbstractEntity{
私有最终int id;
私有字符串名称;
受保护的抽象实体(int-id,字符串名称){
this.id=id;
this.name=名称;
}
私有方法(){
...
}
抽象受保护的void someAbstractMethods(){
...
}
}
公共最终类MyEntity扩展了AbstractEntity{
公共静态最终实体_1=新的MyEntity(1,“实体1”,“foo”);
公共静态最终实体_2=新MyEntity(2,“实体2”,“酒吧”);
公共静态最终实体_3=新的MyEntity(3,“实体3”,“baz”);
public static final Set ALL=Collections.unmodifiableSet(新树集(Arrays.asList(ENTITY_1、ENTITY_2、ENTITY_3));
私人最终字符串foo;
私有MyEntity(int id、字符串名称、字符串foo){
super(id,name);
this.foo=foo;
}
}
我看到的缺陷是,在开发过程中添加新实体时,我也必须将其添加到ALL集合中。这让我很恼火。这是一种冗余,是bug的来源
然后,我考虑将枚举用作实体类,在实体类中可以定义entitiy对象,并隐式地在values()数组中包含所有对象引用。
但这不起作用,因为Java中不可能有基类(AbstractEntity)和多重继承
下一个想法是使用带有默认方法的接口来代替抽象基类,并作为实体定义实现此接口的枚举。
但这样我就不能在基类(接口)中定义int-id和String-name,而必须在每个子类中定义它
我少了一些语法糖吗?
这里的最佳实践是什么?类似这样的东西可以通过反射来实现
public final class MyEntity extends AbstractEntity{
public static final ENTITY_1 = new MyEntity(1, "Entity 1", "foo");
public static final ENTITY_2 = new MyEntity(2, "Entity 2", "bar");
public static final ENTITY_3 = new MyEntity(3, "Entity 3", "baz");
public static final Set<MyEntity> ALL;
static {
final Set<MyEntity> all = new TreeSet<>();
// Find all static fields in this class which are instances of this class:
final Field[] fields = MyEntity.class.getDeclaredFields();
for ( Field f : fields ) {
if ( f.getType() == MyEntity.class ) {
if ( Modifier.isStatic( f.getModifiers() ) {
all.add((MyEntity)f.get(null));
}
}
}
ALL = Collections.unmodifiableSet( all );
}
private final String foo;
private MyEntity(int id, String name, String foo){
super(id, name);
this.foo = foo;
}
}
公共最终类MyEntity扩展了AbstractEntity{
公共静态最终实体_1=新的MyEntity(1,“实体1”,“foo”);
公共静态最终实体_2=新MyEntity(2,“实体2”,“酒吧”);
公共静态最终实体_3=新的MyEntity(3,“实体3”,“baz”);
公共静态最终设置全部;
静止的{
最终设置全部=新树集();
//查找此类中属于此类实例的所有静态字段:
最终字段[]字段=MyEntity.class.getDeclaredFields();
用于(字段f:字段){
if(f.getType()==MyEntity.class){
if(Modifier.isStatic(f.getModifiers()){
all.add((MyEntity)f.get(null));
}
}
}
ALL=集合。不可修改集(ALL);
}
私人最终字符串foo;
私有MyEntity(int id、字符串名称、字符串foo){
super(id,name);
this.foo=foo;
}
}
编写通用实用程序函数initializeEntitySet(类entityClass)这应该是直截了当的。如评论中所述,我宁愿使用
枚举来存储每个实体的实例。您可以向枚举构造函数添加参数,以便随后可以实例化和存储实体值
接下来,我为您提供了一个解决方案,使您的集合
存储所有实例,并为类型a的实体提供了一个枚举
,为类型B的实体提供了另一个枚举(两者都继承自ALL集合中使用的AbstractEntity
)。所有集合在从枚举中检索值的静态部分上填充,因此,您只需在枚举中添加条目即可添加新值
Entities.java
public class Entities {
// Entities of class A
private enum EntitiesOfA {
ENTITY_A_1(1, "EntityA 1", "foo"), // A1
ENTITY_A_2(2, "EntityA 2", "bar"), // A2
ENTITY_A_3(3, "EntityA 3", "baz"); // A3
private MyEntityA entity;
private EntitiesOfA(int id, String name, String foo) {
this.entity = new MyEntityA(id, name, foo);
}
public MyEntityA getEntity() {
return this.entity;
}
}
// Entities of class B
private enum EntitiesOfB {
ENTITY_B_1(4, "EntityB 1", 10), // B1
ENTITY_B_2(5, "EntityB 2", 11), // B2
ENTITY_B_3(6, "EntityB 3", 12); // B3
private MyEntityB entity;
private EntitiesOfB(int id, String name, int value) {
this.entity = new MyEntityB(id, name, value);
}
public MyEntityB getEntity() {
return this.entity;
}
}
// All Entities
public static final Set<AbstractEntity> ALL;
static {
// I use HashSet instead of TreeSet because I have
// not implemented the comparable interface
Set<AbstractEntity> allEntities = new HashSet<>();
for (EntitiesOfA entity : EntitiesOfA.values()) {
allEntities.add(entity.getEntity());
}
for (EntitiesOfB entity : EntitiesOfB.values()) {
allEntities.add(entity.getEntity());
}
ALL = Collections.unmodifiableSet(allEntities);
}
public static void main(String[] args) {
for (AbstractEntity entity : ALL) {
System.out.println("Entity ID = " + entity.getId() + " NAME = " + entity.getName());
entity.someAbstractMethods();
if (entity instanceof MyEntityA) {
MyEntityA a = (MyEntityA) entity;
System.out.println("Entity A with foo = " + a.getFoo());
a.someMethods();
} else if (entity instanceof MyEntityB) {
MyEntityB b = (MyEntityB) entity;
System.out.println("Entity B with value = " + b.getValue());
b.someMethods();
} else {
System.err.println("ERROR: Unrecognised subclass");
}
}
}
}
public abstract class AbstractEntity {
private final int id;
private String name;
protected AbstractEntity(int id, String name) {
this.id = id;
this.name = name;
}
public int getId() {
return this.id;
}
public String getName() {
return this.name;
}
public void someMethods() {
// A
}
protected abstract void someAbstractMethods();
}
MyEntityA.java
公共最终类MyEntityA扩展了AbstractEntity{
private final String foo;
public MyEntityA(int id, String name, String foo) {
super(id, name);
this.foo = foo;
}
public String getFoo() {
return this.foo;
}
@Override
protected void someAbstractMethods() {
// Some code
}
private final int value;
public MyEntityB(int id, String name, int value) {
super(id, name);
this.value = value;
}
public int getValue() {
return this.value;
}
@Override
protected void someAbstractMethods() {
// Some code
}
}
MyEntityB.java
公共最终类MyEntityB扩展了AbstractEntity{
private final String foo;
public MyEntityA(int id, String name, String foo) {
super(id, name);
this.foo = foo;
}
public String getFoo() {
return this.foo;
}
@Override
protected void someAbstractMethods() {
// Some code
}
private final int value;
public MyEntityB(int id, String name, int value) {
super(id, name);
this.value = value;
}
public int getValue() {
return this.value;
}
@Override
protected void someAbstractMethods() {
// Some code
}
}
请注意:
- 如果愿意,可以用
VAL(new MyEntityA(…)
替换枚举中的构造函数。在这种情况下,可以合并EntitesOfA
和EntitesOfB
以拥有所有实体,并将构造函数与AbstractEntity
一起使用。您还可以删除集合
public class AllEntities {
private enum Entities {
ENTITY_A_1(new MyEntityA(1, "EntityA 1", "foo")), // A1
ENTITY_A_2(new MyEntityA(2, "EntityA 2", "bar")), // A2
ENTITY_A_3(new MyEntityA(3, "EntityA 3", "baz")), // A3
ENTITY_B_1(new MyEntityB(4, "EntityB 1", 10)), // B1
ENTITY_B_2(new MyEntityB(5, "EntityB 2", 11)), // B2
ENTITY_B_3(new MyEntityB(6, "EntityB 3", 12)); // B3
private AbstractEntity entity;
private Entities(AbstractEntity entity) {
this.entity = entity;
}
public AbstractEntity getEntity() {
return this.entity;
}
}
// All Entities
public static final Set<AbstractEntity> ALL;
static {
// I use HashSet instead of TreeSet because I have
// not implemented the comparable interface
Set<AbstractEntity> allEntities = new HashSet<>();
for (Entities entity : Entities.values()) {
allEntities.add(entity.getEntity());
}
ALL = Collections.unmodifiableSet(allEntities);
}
公共类allenties{
私有枚举实体{
实体A_1(新的MyEntityA(1,“EntityA 1”,“foo”),//A1
实体2(新的MyEntityA(2,“实体2”,“条形”),//A2
实体3(新的MyEntityA(3,“EntityA 3”,“baz”),//A3
实体1(新的MyEntityB(4,“EntityB 1”,10)),//B1
实体2(新的MyEntityB(5,“EntityB 2”,11)),//B2
实体3(新的MyEntityB(6,“EntityB 3”,12));//B3
私人抽象实体;
私有实体(抽象实体){
this.entity=实体;
}
公共抽象实体getEntity(){
返回该实体;
}
}
//所有实体
公共静态最终设置全部;
静止的{
//我使用HashSet而不是TreeSet,因为我有
//没有实现可比较的接口
Set allenties=new HashSet();
对于(实体:Entities.values()){
添加(entity.getEntity());
}
ALL=集合。不可修改集(allEntities);
}
- 我添加了一个主要的测试方法,但您也可以删除它
这听起来并不简单