注释上的通用类类型

时间:2013-07-29 04:36:10

标签: java generics

这可能吗?

class MyService<T> {

    @MyAnnotation(T.class)
    private String myProperty;
}

编译器不喜欢它。我怎么能这样做?

更新

我发现我做不到。见Error setting annotation value as Class<?> from a constant, why?

2 个答案:

答案 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(请参阅herehere)和/或Guice(请参阅herehere)。这两个库提供了在运行时注入(或以其他方式确定)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;
}

您可以创建通用参数已知的具体服务实例,然后您可以使用注释,因为您已知该类。是的,这有点乏味。