这可能吗?
class MyService<T> {
@MyAnnotation(T.class)
private String myProperty;
}
编译器不喜欢它。我怎么能这样做?
更新
我发现我做不到。见Error setting annotation value as Class<?> from a constant, why?。
答案 0 :(得分:6)
这是不可能的。
注释的参数必须是编译时常量值(例如String,数字常量或类文字,例如User.class
),并且在编译时未定义泛型参数T
时间。
此外,如果T
是一个类型参数,那么T.class
在任何情况下都不是有效的Java代码,因为名为 type erasure (参见here }和here)。如果您需要知道运行时类型参数T
的类是什么,有一些方法。例如:
class Repository<T> {
private final Class<T> type;
Repository(Class<T> type) { this.type = type; }
T load(int id) { ... can use type here ... }
}
另外,请务必查看Google Guava(请参阅here和here)和/或Guice(请参阅here和here)。这两个库提供了在运行时注入(或以其他方式确定)T
表示的类的方法,而不必在构造函数中传递它。
这些库使用的技术基于以下事实:尽管您无法访问给定Class<?>
的类型参数信息,但您可以访问该类的超类型信息。因此,如果您有abstract class Service<T>
并且您有class MyService extends Service<String>
,则可以使用Class<MyService>
在其上调用getGenericSuperclass()
并使用结果获取{的值{1}},即T
。这很乏味,容易出错,因此请务必使用库来为您完成。
答案 1 :(得分:1)
由于类型擦除,不可能。你可以这样做。
class MyConcreteService extends MyService<String> {
@MyAnnotation(String.class)
private String myProperty;
}
您可以创建通用参数已知的具体服务实例,然后您可以使用注释,因为您已知该类。是的,这有点乏味。