[英]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>
事件,尽管E
和T
将始终是相同的类型。
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? 有更简单的方法吗?
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.