这可能吗?
class MyService<T> {
@MyAnnotation(T.class)
private String myProperty;
}
编译器不喜欢它。我怎样才能做到这一点?
更新
我发现我做不到。请参阅从常量将注释值设置为 Class<?> 时出错,为什么?.
这可能吗?
class MyService<T> {
@MyAnnotation(T.class)
private String myProperty;
}
编译器不喜欢它。我怎样才能做到这一点?
更新
我发现我做不到。请参阅从常量将注释值设置为 Class<?> 时出错,为什么?.
这是不可能的。
注解的参数必须是编译时常量值(如字符串、数值常量或类文字,如),并且在编译时不定义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
。这是乏味的,容易出错的,所以一定要使用一个库来为你做这件事。
由于类型擦除,这是不可能的。你可以做这样的事情。
class MyConcreteService extends MyService<String> {
@MyAnnotation(String.class)
private String myProperty;
}
您可以在通用参数已知的情况下创建服务的具体实例,然后您可以使用注释,因为您知道该类。是的,这有点乏味。