Java Enum - 以后播放的商店类型

时间:2015-09-07 18:05:17

标签: java class types casting enums

我有一个枚举,表示特定表中的所有列值。现在我想存储一个每个枚举元素的类型,这个元素被查询以供稍后的转换。

public enum Value {

    MEMBER1(?...?),
    MEMBER2(?...?);

    private final ?...? type;

    Value(?...? type) {
        this.type = type;
    }

    public ?...? getType() {
        return type;
    }

}

我现在不需要代替?...?。可能是MyClassA.classClass但是如何将此值用于此操作:

MEMBER1.getType() instance = (MEMBER1.getType()) object;

对于我来说,这对于与java进行数据库通信非常重要。

更新:我的意思是此操作。

END UPDATE:存在逻辑错误。如果我知道不同的类型,我可以简单地创建多个方法,因为我有一个api规范。

4 个答案:

答案 0 :(得分:5)

你是对的。枚举应定义如下

public enum Value {

   MEMBER1(String.class),
   MEMBER2(Integer.class);

   private final Class<?> type;
   private Value(Class<?> type) {
       this.type = type;
   }

   public Class<?> getType(){
       return this.type;
   }
}

第二部分实际上是你不想做的事情,因为你已经知道你想要将你的对象投射到什么类型(在你的情况下是MyClassA)所以你可以直接投射如下

//I know what is the target type so I don't have to fetch the type from my enum
MyClassA instance = (MyClassA) object;

一旦您需要在未知数据类型上构建逻辑,就可以执行类似

的操作
Object o = getTheObjectSomewhere();
if(o.getClass().isAssignableFrom(MEMBER1.getType()){
    String s = (String) o;
    System.out.println("Target type is string!");
    doSomething();
} else if (o.getClass().isAssignableFrom(MEMBER2.getType()){
    Integer i = (Integer) i;
    System.out.println("Target type is integer!");
    doSomethingElese();
}

您可能希望稍后根据对象的类型搜索列。然后,您可以创建一个方法来获取列

public Value getColumnByObjectType(Object o){
    for(Value v : Value.values()){
        if(v.getType().equals(o.getClass()){
            return v;
        }
    }
    return null;
}

并使用它来搜索列

Object o = getObjectSomewhere();
Value column = getColumnByObjectType(o);

要根据下面的评论获取用户对象,您可以使用JPA

执行以下操作
public Object getUserObject(int id, Value v){
    TypedQuery<?> q = DBUtils.getEntityManager().createQuery("select u.:column from User u where u.id = :id",v.getType());
    q.setParameter("column", v.toString());
    q.setParameter("id", id);
    q.setMaxResult(1);
    return q.getSingleResult();
}

答案 1 :(得分:2)

您可以通过存储对象的Class并在必要时使用它来进行转换:

class Test {

    public static void main(String[] arguments) throws Exception {
        Object object = new MyClassA();
        Class<MyClassA> clazz = Value.MEMBER1.getType();
        MyClassA instance = clazz.cast(object);
        System.out.println(instance);
    }

}

enum Value {

    MEMBER1(MyClassA.class),
    MEMBER2(MyClassB.class);

    private final Class<?> clazz;

    Value(Class<?> clazz) {
        this.clazz = clazz;
    }

    @SuppressWarnings("unchecked")
    public <T> Class<T> getType() {
        return (Class<T>) clazz;
    }

}

class MyClassA { }
class MyClassB { }

答案 2 :(得分:0)

  

如何将此值用于此操作:

MyClassA instance = (MEMBER1.getType()) object;

使用 instanceof 检查对象类型。

MyClassA instance;
if (object instanceof MyClassA && object instanceof MEMBER1.getType()){ 
 instance = (MyClassA) object;
}

答案 3 :(得分:0)

  

我有一个枚举,表示特定表中的所有列值。现在   我想存储每个枚举元素的类型,稍后查询   铸造。

一般来说,这不可能按照您希望的方式完成。

你想要的是enum持有异构类型安全容器的密钥(Essential Java,2nd Ed。)。

不幸的是,Java类对象是通用的(例如String.classClass<String>)和 Java枚举和泛型不能很好地协作

虽然可以将Class对象存储为枚举中的字段,但您的Class对象将在该过程中丢失其类型信息。当您访问该字段时,您仍需要手动重新确认类型链接...这将需要一个不安全的强制转换。我不知道周围有什么办法。

例如,您的枚举可能有一个名为colClassToken的字段,您打算在其中存储表中关联列的类型:

public enum TableColumn {
    MEMBER1(String.class),
    MEMBER2(Integer.class);

    private Class<?> e_colToken;

    TableColumn(Class<?> tok) { this.e_colToken = tok; }

    public Class<?> getColumnToken() { return this.e_colToken; }

    :
    :
}

您现在希望能够使用Class对象的cast()方法在您访问表中的列时重新确定类型链接(例如,使用类似的惯用法):

String myColumn = MEMBER1.getColumnToken().cast(myTable.getCol(MEMBER1));
但是,这不会编译。由于类对象的类型已在枚举字段中丢失(并且因为您无法生成枚举),因此编译器无法保证cast()操作的类型安全性。