0

这可能吗?

class MyService<T> {

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

编译器不喜欢它。我怎样才能做到这一点?

更新

我发现我做不到。请参阅从常量将注释值设置为 Class<?> 时出错,为什么?.

4

2 回答 2

6

这是不可能的。

注解的参数必须是编译时常量值(如字符串、数值常量或类文字,如),并且在编译时不定义User.class泛型参数。T

此外,如果T是一个类型参数,那么T.class在任何情况下都不是有效的 Java 代码,因为这种情况称为类型擦除(请参阅此处此处)。如果您需要知道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(请参阅此处此处)和/或 Guice(请参阅此处此处)。这两个库提供了在运行时注入(或以其他方式确定)所代表的类的方法T,而无需在构造函数中传递它。

这些库使用的技术基于这样一个事实:尽管您无法访问给定 的类型参数的信息,但您可以访问Class<?>该类的超类型的信息。所以,如果你有,比如说abstract class Service<T>你有一个class MyService extends Service<String>,你可以使用 aClass<MyService>来调用getGenericSuperclass()它并使用结果来获取 的值T,即String。这是乏味的,容易出错的,所以一定要使用一个库来为你做这件事。

于 2013-07-29T04:44:29.177 回答
1

由于类型擦除,这是不可能的。你可以做这样的事情。

class MyConcreteService extends MyService<String> {

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

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

于 2013-07-29T04:47:11.503 回答