将Class <T>强制转换为Class <E的最简单方法是扩展Enum <E >>而不丢失类型信息

Feu*_*mel 5 java generics enums casting

我有一个方法createFoo(),为此创建Foo<T>使用Class<T>实例的实例T.现在我想扩展该方法以将使用枚举类型进行的调用转发给该方法createEnumFoo().从第一个方法调用第二个方法似乎是非平凡的.下面是我如何设法使用两个未经检查的强制转换和一个额外的方法,我想摆脱所有这些的例子.

该方法castEnumType()是必需的,因为我找不到一种方法来将a转换Class<?>为a Class<E extends Enum<E>>而没有E绑定某处.这涉及一个未经检查的演员,因为我还没有找到一种方法来使用它Class.asSubclass().在创建实例之后Foo,我需要将它从事件转换Foo<E>Foo<T>事件,E并且T将始终是相同的类型.

我无法削弱签名,createEnumFoo()因为它正在调用Enum.valueOf(enumType, ...)并要求其结果为类型E.

final class Example {
    <E extends Enum<E>> Foo<E> createEnumFoo(Class<E> enumType) {
        // This makes use of e.g. Enum.valueOf(enumType, ...).
        return null;
    }

    <E extends Enum<E>> Class<E> castEnumType(Class<?> enumType) {
        return (Class<E>) enumType;
    }

    <T> Foo<T> createFoo(Class<T> type) {
        if (Enum.class.isAssignableFrom(type))
            return (Foo<T>) createEnumFoo(castEnumType(type));
        else
            // Here we would do something else or maybe throw an exception.
            return null;
    }

    interface Foo<T> {
    }
}
Run Code Online (Sandbox Code Playgroud)

有更简单的方法吗?


一些背景

为了澄清我面临的问题,我将解释这个问题是如何在我正在进行的项目中出现的:

在我遇到这个问题的代码中,Foo<T>实际上Converter<T>,这是一个允许TJSON值序列化和反序列化的实例的接口:

public interface Converter<T> {
    JsonObject encode(T value);

    T decode(JsonObject data);
} 
Run Code Online (Sandbox Code Playgroud)

createFoo()实际上是一种方法,converterForType()这需要一个Class<T>实例,并动态地分派给为数众多的创建/包含常用的Java类型和类型特定的项目转换静态方法和字段.通常,当需要转换器时,直接访问适当的方法/字段,但有些地方只在运行时知道类型,这converterForType()是使用的地方.

现在我想扩展该方法,通过将枚举类型转换为包含枚举常量名称的JSON字符串来自动处理枚举类型.这就是我需要调用方法enumConverter()的原因converterForType().这是执行enumConverter():

public static <E extends Enum<E>> Converter<E> enumConverter(final Class<E> enumClass) {
    return new Converter<E>() {
        public JsonObject encode(E value) {
            return Json.convert(value.name());
        }

        public E decode(JsonObject data) {
            return Enum.valueOf(enumClass, data.asString());
        }
    };
}
Run Code Online (Sandbox Code Playgroud)

Ahm*_*sid 2

那怎么样,对 createEnumFoo 方法使用原始类型
编辑:修复了评论中 @Feuermurmel 报告的编译错误

@SuppressWarnings({ "unchecked", "rawtypes" })
final class Example
{
    <E extends Enum<E>> Foo<E> createEnumFoo(Class enumType)
    {
        // This makes use of e.g. Enum.valueOf(enumType, ...).
        Enum x = Enum.valueOf(enumType, "x");
        return (Foo<E>) x;
    }

    <T extends Enum> Foo<T> createFoo(Class<T> type)
    {
        if (Enum.class.isAssignableFrom(type))
            return (Foo<T>) createEnumFoo(type);
        else
            // Here we would do something else or maybe throw an exception.
            return null;
    }

    interface Foo<T>
    {
    }
}
Run Code Online (Sandbox Code Playgroud)