如何在java中强制转换为CRTP?
我有一个非常简单的例子,我做了一些基本的通用赋值:
final Detail detail = field.getAnnotation(Detail.class); final String example = detail.example(); final Class type = field.getType(); if (List.class.isAssignableFrom(type)) ... else if (Enum.class.isAssignableFrom(type)) setValue(contract, field, Enum.valueOf(type, example)); else if (...) .....
但是Enum.valueOf()有点难以调用,在我的例子中,错误是:
java.lang.Enum中的valueOf(java.lang.Class,java.lang.String)不能应用于(java.lang.Class,java.lang.String)
这非常有意义,因为type是Class
。 但由于Enum
是CRTP,我找不到一种好的方法来转换类型以使编译器满意。 是使用原始类型Enum.valueOf((Class)type, example))
唯一的答案? 它给了我2个警告,而不是只有一个。
以下行只有一个警告:
... setValue( contract, field, Enum.valueOf( type.asSubclass( Enum.class ), example ) ); ...
您可以编写一个辅助方法来捕获满足Enum要求的“T”类型:
private > T helper(Class> type, String example) { return Enum.valueOf((Class )type, example); }
这应该只有一个警告
然后你可以像使用它一样
else if (Enum.class.isAssignableFrom(type)) setValue(contract, field, helper(type, example));
编辑:好的,那怎么样:
private > Object helper(Class> type, String example) { return Enum.valueOf((Class )type, example); }
我不认为删除编译器警告是可能的
最好的情况是将所有错误减少到像@tangens那样的错误。
找到两个论坛post,显示不成功的答案,并解释了为什么多一点。
- http://forums.sun.com/thread.jspa?threadID=5215278
- http://forums.sun.com/thread.jspa?threadID=694354
所以我把一个完整的例子放在一起来展示我所看到的问题。
import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; import java.lang.reflect.Field; import java.util.List; public class Test { @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.FIELD) public @interface Detail { String example(); } public enum ExampleEnum { FOO_BAR, HELLO_WORLD } @Detail(example = "FOO_BAR") public ExampleEnum test; public static void main(String[] args) throws SecurityException, NoSuchFieldException, IllegalArgumentException, IllegalAccessException { populate(new Test()); } public static void populate(Object o) throws IllegalArgumentException, IllegalAccessException, SecurityException, NoSuchFieldException { final Field field = o.getClass().getField("test"); final Detail detail = field.getAnnotation(Detail.class); System.out.println("Annotation = " + detail); final String example = detail.example(); final Class> type = field.getType(); System.out.println("Field Class = " + type.getName()); if (List.class.isAssignableFrom(type)) { } else if (Enum.class.isAssignableFrom(type)) { Class extends Enum> enumType = type.asSubclass(Enum.class); // Enum is a raw type. References to generic type Enum should be parameterized Enum val = Enum.valueOf(enumType, example); // 1) Enum is a raw type. References to generic type Enum should be parameterized // 2) Type safety: Unchecked invocation valueOf(Class, String) of the generic // method valueOf(Class, String) of type Enum field.set(o, val); } } }