代码之家  ›  专栏  ›  技术社区  ›  Marcin Cylke

泛型Java枚举

  •  8
  • Marcin Cylke  · 技术社区  · 15 年前

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

    感谢您的帮助。

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

    public class XEnumTypeHandler extends CommonEnumTypeHandler<X> {
    }
    

    当前代码:

    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;
     }
    }
    

    我在上面的代码中添加了错误标记,错误消息的顺序如下:

    • t无法解决
    • 方法值()未定义用于 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);
        }
    }
    

    从这个类继承:

    public class SalesChannelTypeHandler extends CommonEnumTypeHandler<SalesChannel> {
    
        public SalesChannelTypeHandler() {
            super(SalesChannel.class);
        }
    
        public SalesChannelTypeHandler(Class<SalesChannel> clazz) {
            super(clazz);
        }
    
    }
    
    2 回复  |  直到 15 年前
        1
  •  8
  •   polygenelubricants    15 年前

    我不知道你在做什么(用文字概括一下会很好),但是:

    • 你做不到 isAssignableFrom(T) (你需要一个 Class 对象),你不能这样做 instanceof T 二者之一(仿制药是非真实化的)。你 可以 想通过 Class<T> 请键入标记。
    • 你看过吗 EnumMap ?

    也见


    目前还不清楚需要什么,但可能是沿着这条线:

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

    所以我们使用 Enum.valueOf 带类型标记的 Class<T extends Enum<T>> 并要求 enum 具有给定名称的常量。 valueOf 不是 不区分大小写,但根据惯例, 全部的 常量应该是大写的,所以我们只需取查询字符串并将其转换为 .toUpperCase() .

        2
  •  4
  •   BalusC    15 年前

    正如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);
            }
        }
    }
    

    然后您可以使用如下:

    public class XEnumTypeHandler extends CommonEnumTypeHandler<X> {
        public XEnumTypeHandler() {
            super(X.class);
        }
    }