泛型类型中的 Java 枚举

发布于 2024-09-06 08:52:45 字数 2377 浏览 4 评论 0 原文

我想为 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 无法解析
  • The method value() is undefined for 类型 T
  • 方法 value() 未定义 类型 T
  • 方法 value() 未定义 类型 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);
    }

}

I'd like to create a generic enum-based mapper for IBatis. I'm doing this with the below code. This does have compile time errors, which I don't know how to fix. Maybe my solution is just plain wrong (keep in mind the use of IBatis), in such case please suggest something better.

Any help appreciated.

What I want to achieve is to define subsequent mappers as:

public class XEnumTypeHandler extends CommonEnumTypeHandler<X> {
}

The current code:

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

I've added error markings to the above code, the error messages are in order:

  • T cannot be resolved
  • The method value() is undefined for
    the type T
  • The method values() is undefined for
    the type T
  • The method values() is undefined for
    the type T

I've solved this issue with the following code:

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

Inheriting from this class I do:

public class SalesChannelTypeHandler extends CommonEnumTypeHandler<SalesChannel> {

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

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

}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

小矜持 2024-09-13 08:52:45

我不确定你在做什么(用文字进行一般概述会很好),但是:

  • 你不能做 isAssignableFrom(T) (你需要一个 Class object),并且你也不能做 instanceof T (泛型是非具体化的)。您可能想要传递Class类型令牌。
  • 您是否看过 EnumMap< /a>?

另请参阅


目前还不清楚需要什么,但也许是这样的:

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> ; ,并向其询问具有给定名称的enum常量。 valueOf NOT 不区分大小写,但按照惯例,所有 常量都应为大写,因此我们只需获取查询字符串并将其转换为 <代码>.toUpperCase()

I'm not sure what you're doing (a general overview in words would be nice), but:

  • You can't do isAssignableFrom(T) (you need a Class object), and you can't do instanceof T either (generics are non-reified). You may want to pass Class<T> type tokens instead.
  • Have you looked at EnumMap?

See also


It's still not clear what is desired, but perhaps it's something along the lines of this:

enum Color { BLACK, WHITE; }

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

So we use Enum.valueOf that takes a type token Class<T extends Enum<T>>, and ask it for the enum constant with a given name. valueOf is NOT case-insensitive, but by conventions, all constants should be in uppercase, so we simply take the query string and turn it .toUpperCase().

潜移默化 2024-09-13 08:52:45

正如 Polygenelubricants 所指出的,您需要传递具体的运行时类型,例如 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);
    }
}

As pointed by Polygenelubricants, you need to pass concrete runtime types around, e.g. Class<?> instead of syntactic compiletime types like generic parameters. Here's a rewrite how you could use it:

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

Which you can then use as follows:

public class XEnumTypeHandler extends CommonEnumTypeHandler<X> {
    public XEnumTypeHandler() {
        super(X.class);
    }
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文