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

在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

现在正如所说的杰克逊不会将其序列化开箱即用,所以我编写了通用模块,它允许序列化此类复杂的地图。


要使用它,您需要做的就是像这样注释您的“关键”类:


@KeySerializable

class 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 

      }


   } 


ABOUTYOU
浏览 97回答 2
2回答

哔哔one

如果您的目标是断言仅接受带注释的类,那么您几乎没有解决方法选项:编写一个在编译时执行断言的注释处理器(参见@NonNull等如何工作)。这是一项有趣的工作,但并不简单,因为编译/类型系统对于许多经验丰富的 Java 开发人员来说是全新的。使用某种形式的 AOP(AspectJ、Spring AOP 等)来“建议”带有装饰器的所有带注释的方法,该装饰器的职责是断言参数具有相同的注释。使用在运行时显式检查parameter.getClass().isAnnotationPresent(MyAnnotation.class)

守候你守候我

像Checker Framework这样的工具会插入编译器中,以类似于您所请求的方式限制通用实例化。它作为注释处理器实现,并提供正确使用的编译时保证。例如,您可以写class MyList<T extends @NonNull Object> {...}。Checker Framework 使您能够构建自己的检查器,它强制执行您喜欢的任何规则@KeySerializable。在您的情况下,规则可能非常简单,您只需定义几个类型限定符并使用子类型检查器- 至少一开始是这样。请注意,要使 Checker 框架使用注释工作@KeySerializable,该注释必须是类型注释而不是声明注释。
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Java