在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” liek“ andy”,“ mike”,“ john”。内部地图包含给定运动员在给定期间内执行的活动。
所以让我们说安迪(Andy)正在慢跑一天,而不是参加比赛:
new SportsmanActivities().get("andy").put(TimeRange.of('2012-12-01,'2012-12-02'), List.with(new JoggingActivity)) // did some pseudo code here for readablity
现在,正如杰克逊所说的那样,它不会立即进行序列化,因此我编写了通用模块,可以对这种复杂的地图进行序列化。
要使用该功能,您需要做的就是这样注释“ key”类:
@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
}
}
答案 0 :(得分:3)
如果您的目标是断言仅接受带注释的类,那么您只有几个解决方法:
parameter.getClass().isAnnotationPresent(MyAnnotation.class)
明确检查答案 1 :(得分:1)
诸如Checker Framework之类的工具会插入到编译器中,以类似于您请求的方式的方式限制泛型实例化。它被实现为注释处理器,并为正确使用提供了编译时保证。
For example,您可以编写class MyList<T extends @NonNull Object> {...}
。
通过Checker Framework,您可以build your own checker来实施您喜欢的关于@KeySerializable
的任何规则。就您而言,规则可能是如此简单,以至于您只需要定义几个类型限定符并使用Subtyping Checker即可-至少在一开始。
请注意,要使Checker框架使用@KeySerializable
注释,该注释必须是类型注释,而不是声明注释。