简体   繁体   English

最简单的方法来转换类 <T> 到一个班级 <E extends Enum<E> &gt;不丢失类型信息

[英]Simplest way to cast a Class<T> to a Class<E extends Enum<E>> without losing type information

I have a method createFoo() that creates instances of Foo<T> using the Class<T> instance for that T . 我有一个方法createFoo()创建的实例Foo<T>使用Class<T>实例为T Now I want to extend that method to forward calls that are made using an enum type to the method createEnumFoo() . 现在我想扩展该方法以将使用枚举类型进行的调用转发给方法createEnumFoo() Calling the second method from the first one seems to be non-trivial. 从第一个方法调用第二个方法似乎是非平凡的。 Below is an example of how I managed to do it using two unchecked casts and an extra method, all of which I would like to get rid of. 下面是我如何设法使用两个未经检查的强制转换和一个额外的方法,我想摆脱所有这些的例子。

The method castEnumType() is required because I couldn't find a way to cast a Class<?> to a Class<E extends Enum<E>> without having the E bound somewhere. 方法castEnumType()是必需的,因为我找不到将Class<?> castEnumType()转换为Class<E extends Enum<E>>而不将E绑定到某处的方法。 This involves an unchecked cast because I have not found a way to do it using Class.asSubclass() . 这涉及一个未经检查的强制转换,因为我还没有找到使用Class.asSubclass() After creating the instance of Foo , I need to cast it from Foo<E> to Foo<T> event though E and T will always be the same types. 在创建Foo实例之后,我需要将它从Foo<E>Foo<T>事件,尽管ET将始终是相同的类型。

I can't weaken the signature of createEnumFoo() because it is calling Enum.valueOf(enumType, ...) and requires the result of this to be of type E . 我无法削弱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> {
    }
}

Is there a simpler way to do this? 有更简单的方法吗?


Some context 一些背景

To clarify the problem I'm facing, I'll explain how this problem actually arose in a project I'm working on: 为了澄清我面临的问题,我将解释这个问题是如何在我正在进行的项目中出现的:

In the code where I came across this problem, Foo<T> is actually Converter<T> , which is an interface which allows an instance of T to be serialized and de-serialized from and to a JSON value: 在遇到此问题的代码中, Foo<T>实际上是Converter<T> ,它是一个接口,它允许将T实例序列化并反序列化为JSON值:

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

    T decode(JsonObject data);
} 

And createFoo() is actually a method converterForType() which takes a Class<T> instance and dynamically dispatches to a bunch of static methods and fields that create/contain converters for common Java types and types specific to the project. createFoo()实际上是一个方法converterForType() ,它接受一个Class<T>实例并动态调度到一堆静态方法和字段,这些方法和字段创建/包含特定于项目的常见Java类型和类型的转换器。 Normally when a converter is needed, the appropriate method/field is accessed directly but there are some places where the type is only known at runtime, which is where converterForType() is used. 通常,当需要转换器时,直接访问适当的方法/字段,但有些地方只在运行时知道类型,这是使用converterForType()地方。

Now I wanted to extend that method to automatically handle enum types by converting those to JSON strings containing the name of the enum constant. 现在我想扩展该方法,通过将枚举类型转换为包含枚举常量名称的JSON字符串来自动处理枚举类型。 This is why I need to call the method enumConverter() from converterForType() . 这就是我需要从converterForType()调用方法enumConverter() converterForType() This is the implementation of enumConverter() : 这是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());
        }
    };
}

What about this, use raw types for createEnumFoo method 那么,使用createEnumFoo方法的原始类型
Edit: fixed compile error reported by @Feuermurmel in comments 编辑:@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>
    {
    }
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 C#相当于Java类 <E> 和E扩展枚举 <E> - C# equivalent of java Class<E> and E extends Enum<E> 为什么“类型绑定不匹配:类型? 扩展T不是有界参数的有效替代品 <E extends Enum<E> &gt;枚举类型 <E> “? - Why ”Type Bound mismatch: The type ? extends T is not a valid substitute for the bounded parameter <E extends Enum<E>> of the type Enum<E>“? 在不丢失类型信息的情况下获取类 List 的类对象的正确方法是什么? - What is the correct way to obtain the class object for class List without losing type information? 在类型为T的泛型类中,如果T为List,如何查找E. <E> - On a generic class of type T, how to find E if T is List<E> 如何使用扩展类 <E extends Comparable<E> &gt; - How to extend Generic abstract Class with <E extends Comparable<E>> 是我的空“公共课 xList<E> 扩展数组列表<E> “ 具体的? - Is my empty "public class xList<E> extends ArrayList<E>" concrete? 类型参数为E的子类的泛型E - Generic class E with type parameter to be a subclass of E 我怎样才能转发到班级'E型或至少在没有警告的情况下安全地进行? - How can I downcast to class' type E or at least make it in a safe way without warnings? 获取参数化类T的扩展Enum的实际枚举类<?> - Get actual enum class of the Parameterized class T extends Enum<?> (错误:valueOf(Class <T> ,String)类型Enum <E> 但不隐藏它)将版本从jdk1.6升级到jdk1.7 - (Error: valueOf(Class<T>, String) of type Enum<E> but does not hide it) Upgrade version from jdk1.6 to jdk1.7
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM