为了账号安全,请及时绑定邮箱和手机立即绑定

Java 泛型类型绑定到具有特定注释的类

Java 泛型类型绑定到具有特定注释的类

ABOUTYOU 2024-01-25 21:39:24
在java中,可以将通用参数绑定到实现特定接口的类,因此以下是可能的interface MyInterface {}class MyClassA implements MyInterface {}class MyBoundedClassA<T extends MyInterface>现在,如果我想将参数绑定到用特定注释注释的类,例如:interface @MyAnnotation {}@MyAnnotationclass 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现在正如所说的杰克逊不会将其序列化开箱即用,所以我编写了通用模块,它允许序列化此类复杂的地图。要使用它,您需要做的就是像这样注释您的“关键”类:@KeySerializableclass TimeRange {  @MyMapKey  LocalDateTime startDate;  @MyMapKey  LocalDateTime endDate;}您可以猜测用@MyMapKey注释的字段将用于生成MapKey。现在我有一个 jackson 类的实现,它动态地序列化作为用 @KeySerialized 注释的“文本映射键”传递的所有内容。签名如下    class MyMapKeySerializer<T> extends JsonSerializer<T> {      serialize (T keyToSerialize) {       // do magic       }   }这是可行的,但我想限制 T 只接受用 @KeySerialized 注释的类,因为只有对于此类类,此方法才有意义。理想情况下,这将是这样的:   class MyMapKeySerializer<T annotatedWith @KeySerializable> extends JsonSerializer<T> {      serialize (T keyToSerialize) {       // do magic       }   } 
查看完整描述

2 回答

?
哔哔one

TA贡献1854条经验 获得超8个赞

如果您的目标是断言仅接受带注释的类,那么您几乎没有解决方法选项:

  1. 编写一个在编译时执行断言的注释处理器(参见@NonNull等如何工作)。这是一项有趣的工作,但并不简单,因为编译/类型系统对于许多经验丰富的 Java 开发人员来说是全新的。

  2. 使用某种形式的 AOP(AspectJ、Spring AOP 等)来“建议”带有装饰器的所有带注释的方法,该装饰器的职责是断言参数具有相同的注释。

  3. 使用在运行时显式检查parameter.getClass().isAnnotationPresent(MyAnnotation.class)


查看完整回答
反对 回复 2024-01-25
?
守候你守候我

TA贡献1802条经验 获得超10个赞

像Checker Framework这样的工具会插入编译器中,以类似于您所请求的方式限制通用实例化。它作为注释处理器实现,并提供正确使用的编译时保证。

例如,您可以写class MyList<T extends @NonNull Object> {...}

Checker Framework 使您能够构建自己的检查器,它强制执行您喜欢的任何规则@KeySerializable。在您的情况下,规则可能非常简单,您只需定义几个类型限定符并使用子类型检查器- 至少一开始是这样。

请注意,要使 Checker 框架使用注释工作@KeySerializable,该注释必须是类型注释而不是声明注释。


查看完整回答
反对 回复 2024-01-25
  • 2 回答
  • 0 关注
  • 96 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信