泛型类型的Java枚举

泛型类型的Java枚举,java,generics,enums,Java,Generics,Enums,我想为IBatis创建一个基于枚举的通用映射器。我用下面的代码来做这件事。这确实有编译时错误,我不知道如何修复。也许我的解决方案是完全错误的(请记住使用IBatis),在这种情况下,请提出更好的建议 谢谢你的帮助 我想要实现的是将后续映射器定义为: public class XEnumTypeHandler extends CommonEnumTypeHandler<X> { } 公共类XEnumTypeHandler扩展了CommonEnumTypeHandler{ } 当前代

我想为IBatis创建一个基于枚举的通用映射器。我用下面的代码来做这件事。这确实有编译时错误,我不知道如何修复。也许我的解决方案是完全错误的(请记住使用IBatis),在这种情况下,请提出更好的建议

谢谢你的帮助

我想要实现的是将后续映射器定义为:

public class XEnumTypeHandler extends CommonEnumTypeHandler<X> {
}
公共类XEnumTypeHandler扩展了CommonEnumTypeHandler{
}
当前代码:

public class CommonEnumTypeHandler<T extends Enum> implements TypeHandlerCallback {

 public void setParameter(ParameterSetter ps, Object o) throws SQLException {
  if (o.getClass().isAssignableFrom(**T**)) { 
   ps.setString(((**T**) o).value().toUpperCase());
  } else
   throw new SQLException("Excpected ParameterType object than: " + o);
 }

 public Object getResult(ResultGetter rs) throws SQLException {
  Object o = valueOf(rs.getString());
  if (o == null)
   throw new SQLException("Unknown parameter type: " + rs.getString());
  return o;
 }

 public Object valueOf(String s) {
  for (T pt : T.**values()**) {
   if (pt.**value()**.equalsIgnoreCase(s))
    return pt;
  }
  return null;
 }
}
公共类CommonEnumTypeHandler实现TypeHandlerCallback{
公共void setParameter(参数设置器ps,对象o)引发SQLException{
如果(o.getClass().isAssignableFrom(**T**)){
ps.setString(((**T**)o.value().toUpperCase());
}否则
抛出新的SQLException(“异常参数类型对象:”+o);
}
公共对象getResult(ResultGetter rs)引发SQLException{
对象o=valueOf(rs.getString());
如果(o==null)
抛出新的SQLException(“未知参数类型:+rs.getString());
返回o;
}
公共对象值(字符串s){
对于(T pt:T.*values()**){
如果(pt.*value()**.equalsIgnoreCase)
返回pt;
}
返回null;
}
}
我已将错误标记添加到上述代码中,错误消息的顺序如下:

  • 这个问题无法解决
  • 未为定义方法值() T型
  • 对于,未定义方法值() T型
  • 对于,未定义方法值() T型
我用以下代码解决了这个问题:

public class CommonEnumTypeHandler<T extends Enum> implements TypeHandlerCallback {

    Class<T> clazz;

    public CommonEnumTypeHandler(Class<T> clazz) {
        this.clazz = clazz;
    }

    public void setParameter(ParameterSetter ps, Object o) throws SQLException {
        if (o.getClass().isAssignableFrom(clazz)) {
            ps.setString(((T) o).name().toUpperCase());
        } else
            throw new SQLException("Excpected " + clazz + " object than: " + o);
    }

    public Object getResult(ResultGetter rs) throws SQLException {
        Object o = valueOf(rs.getString());
        if (o == null)
            throw new SQLException("Unknown parameter type: " + rs.getString());
        return o;
    }

    public Object valueOf(String s) {
        return Enum.valueOf(clazz, s);
    }
}
公共类CommonEnumTypeHandler实现TypeHandlerCallback{
课堂讨论;
公共CommonEnumTypeHandler(类clazz){
this.clazz=clazz;
}
公共void setParameter(参数设置器ps,对象o)引发SQLException{
if(o.getClass().isAssignableFrom(clazz)){
ps.setString(((T)o.name().toUpperCase());
}否则
抛出新的SQLException(“异常的”+clazz+”对象,而不是“+o”);
}
公共对象getResult(ResultGetter rs)引发SQLException{
对象o=valueOf(rs.getString());
如果(o==null)
抛出新的SQLException(“未知参数类型:+rs.getString());
返回o;
}
公共对象值(字符串s){
返回枚举值(clazz,s);
}
}
从这个类继承我做:

public class SalesChannelTypeHandler extends CommonEnumTypeHandler<SalesChannel> {

    public SalesChannelTypeHandler() {
        super(SalesChannel.class);
    }

    public SalesChannelTypeHandler(Class<SalesChannel> clazz) {
        super(clazz);
    }

}
公共类SalesChannelTypeHandler扩展了CommonEnumTypeHandler{
公共SalesChannelTypeHandler(){
超级(SalesChannel.class);
}
公共SalesChannelTypeHandler(clazz类){
超级(clazz);
}
}

我不确定你在做什么(用文字概括一下就好了),但是:

  • 您不能从(t)执行
    isAssignableFrom(t)
    (您需要一个
    对象),也不能执行
    t的instanceof
    (泛型是非具体化的)。您可能希望传递
    类型令牌
  • 你看过吗
另见

我们仍然不清楚想要什么,但也许是这样的:

enum Color { BLACK, WHITE; }

public static void main(String[] args) {
    Color c = Enum.valueOf(Color.class, "black".toUpperCase());
    System.out.println(c); // prints "BLACK"
}

因此,我们使用它获取一个类型标记
Class
,并要求它使用给定名称获取
enum
常量
valueOf
不区分大小写,但按照惯例,所有常量都应该是大写的,因此我们只需获取查询字符串并将其转换为
.toUpperCase()

,正如PolyGene所指出的,您需要传递具体的运行时类型,例如,
Class
,而不是像泛型参数这样的语法编译时类型。以下是您如何使用它的重写:

public abstract class CommonEnumTypeHandler<E extends Enum<E>> implements TypeHandlerCallback {
    private Class<E> enumClass;

    public CommonEnumTypeHandler(Class<E> enumClass) {
        this.enumClass = enumClass;
    }

    public void setParameter(ParameterSetter ps, Object o) throws SQLException {
        if (enumClass.isInstance(o)) {
            ps.setString((enumClass.cast(o)).name().toUpperCase());
        } else {
            throw new SQLException("Excpected ParameterType object than: " + o);
        }
    }

    public Object getResult(ResultGetter rs) throws SQLException {
        try {
            return Enum.valueOf(enumClass, rs.getString());
        } catch (IllegalArgumentException e) {
            throw new SQLException("Unknown parameter type: " + rs.getString(), e);
        }
    }
}
公共抽象类CommonEnumTypeHandler实现TypeHandlerCallback{
私有类;
公共CommonEnumTypeHandler(类enumClass){
this.enumClass=enumClass;
}
公共void setParameter(参数设置器ps,对象o)引发SQLException{
if(枚举类isInstance(o)){
ps.setString((enumClass.cast(o)).name().toUpperCase());
}否则{
抛出新的SQLException(“异常参数类型对象:”+o);
}
}
公共对象getResult(ResultGetter rs)引发SQLException{
试一试{
返回Enum.valueOf(enumClass,rs.getString());
}捕获(IllegalArgumentException e){
抛出新的SQLException(“未知参数类型:”+rs.getString(),e);
}
}
}
然后,您可以按如下方式使用:

public class XEnumTypeHandler extends CommonEnumTypeHandler<X> {
    public XEnumTypeHandler() {
        super(X.class);
    }
}
公共类XEnumTypeHandler扩展了CommonEnumTypeHandler{
公共XEnumTypeHandler(){
超级(X级);
}
}

请添加编译器错误和您实际尝试执行的操作的说明achieve@Marcin:同样,您不能执行
t.values()
,但是如果您传递
Class
的类型标记,您将能够执行。我将给出一个例子,但我仍然不确定您在做什么。只是尝试编写一个通用的“从字符串到已定义类型的枚举”转换器。您传入一个字符串,说“test”并获取enum TestEnum。test@Marcin当前位置我理解你想要实现的目标,但要面对它:!您需要将其作为运行时方法参数传递,而不是作为compiletime泛型类型传递。也许构造函数很有用?@Marcin:那么你想要一个不区分大小写的Enum.valueOf@巴卢斯:好的,我现在明白了,但我不确定你们传递类令牌是什么意思。你能给我举一些这个用法的例子吗?我仍然不确定OP想要什么,但我还是会支持这个。我相信你是正确的=)在
setParameter
中,将
isAssignableFrom
更改为
enumClass。isInstance(o)
@BalusC:无论你知道什么技能,我都想学。@poly:然后尝试重构所有内容,同时保持跨DB兼容。换言之:重新发明/;)@多基因润滑剂。与客户的长时间可用性会议。我得出了类似的解决方案,但巴勒斯比我领先了几秒钟。