【发布时间】:2019-11-06 07:15:14
【问题描述】:
在java中可以将泛型参数绑定到实现特定接口的类,因此可以进行以下操作
interface MyInterface {}
class MyClassA implements MyInterface {}
class MyBoundedClassA<T extends MyInterface>
现在,如果我想将参数绑定到带有特定注释的类的接口,例如:
interface @MyAnnotation {}
@MyAnnotation
class MyClassB {}
class MyBoundedClassB<T extends MyAnnotation> // NOT possible
有可能在 Java 中实现这样的行为吗?
---- 编辑
应要求添加真实世界的示例。稍微修改域以使示例更易于理解。
有众所周知的用于序列化对象的杰克逊库。该库不支持字符串以外的映射键序列化,因此无法开箱即用地进行以下操作
class TimeRange {
LocalDateTime startDate;
LocalDateTime endDate;
}
class SportsmenActivities {
private Map<String, <TimeRange, List<Activity>> sportActivities;
}
在本例中,外部地图的键是“sportsmanCode”,如“andy”、“mike”、“john”。内部地图包含给定运动员在给定时期内进行的活动。
假设安迪慢跑了一天,而不是条目:
new SportsmanActivities().get("andy").put(TimeRange.of('2012-12-01,'2012-12-02'), List.with(new JoggingActivity)) // did some pseudo code here for readablity
现在正如所说,Jackson 不会开箱即用地序列化它,所以我编写了通用模块,它允许序列化这种复杂的地图。
要使用它,你需要做的是像这样注释你的“关键”类:
@KeySerializable
class TimeRange {
@MyMapKey
LocalDateTime startDate;
@MyMapKey
LocalDateTime endDate;
}
您可以猜到,带有@MyMapKey 注释的字段将用于生成 MapKey。
现在我有一个 jackson 类的实现,它动态序列化所有作为“文本映射键”传递的东西,并用 @KeySerializable 注释。签名如下
class MyMapKeySerializer<T> extends JsonSerializer<T> {
serialize (T keyToSerialize) {
// do magic
}
}
这行得通,但我想限制 T 只接受带有 @KeySerializable 注释的类,因为只有这样的类才有意义。理想情况下,这将是这样的:
class MyMapKeySerializer<T annotatedWith @KeySerializable> extends JsonSerializer<T> {
serialize (T keyToSerialize) {
// do magic
}
}
【问题讨论】:
-
注解是“元数据”,可以从注解的元素中查询。它们不被视为类/对象,这意味着它们不能与泛型一起使用。那你为什么需要这个机械师?我确信您的问题有其他解决方案。
-
@n247s:我不认为你是对的。注释是符合合同 Class extends Annotation> 并且每个注释都由这样的类表示。我需要这个机制来限制可以作为参数传递的类的数量。我想保证作为 T 传递的类使用特定注释进行注释(将任何其他类作为 T 传递在 MyBoundedClassB 的上下文中没有意义)
-
@walkeros 注解本身就是类的实例,但是“这个类/方法/变量有那个注解”不是类型系统的一部分。
-
@walkeros 可能,但不是。
-
像Checker Framework 这样的工具插入编译器,以类似于您要求的方式限制通用实例化。 For example,
class MyList<T extends @NonNull Object> {...}。我不知道这是否满足您的用例。您能否让您的示例更加真实,并解释您为什么需要该功能,以便我们了解其他解决方案是否可行?
标签: java generics annotations