簡體   English   中英

Java 泛型類型綁定到具有特定注釋的類

[英]Java generic type bounded to classes with specific annotation

在 java 中,可以將泛型參數綁定到實現特定接口的類,因此可以進行以下操作

interface MyInterface {}

class MyClassA implements MyInterface {}

class MyBoundedClassA<T extends MyInterface>

現在,如果我想將參數綁定到帶有特定注釋的 class 的接口,例如:

interface @MyAnnotation {}

@MyAnnotation
class MyClassB {}

class MyBoundedClassB<T extends MyAnnotation> // NOT possible

是否有可能在 Java 中實現這樣的行為?

- - 編輯

根據要求添加真實世界的示例。 稍微修改域以使示例更易於理解。

有眾所周知的 jackson 庫用於序列化對象。 此庫不支持字符串以外的 map 鍵的序列化,因此無法開箱即用以下操作

class TimeRange {
  LocalDateTime startDate;
  LocalDateTime endDate;

}

class SportsmenActivities {
  private Map<String, <TimeRange, List<Activity>>  sportActivities;
}

在此示例中,外部 map 的鍵是“sportsmanCode”,如“andy”、“mike”、“john”。內部 Map 包含給定運動員在給定時間段內執行的活動。

因此,假設安迪慢跑了一天,而不是條目:

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 不會開箱即用地序列化,所以我編寫了通用模塊,它允許序列化這種復雜的 map。

要使用它,您需要做的是像這樣注釋您的“關鍵” class :

@KeySerializable
class TimeRange {
  @MyMapKey
  LocalDateTime startDate;
  @MyMapKey
  LocalDateTime endDate;

}

正如您所猜測的那樣,帶有@MyMapKey 注釋的字段將用於生成 MapKey。

現在我有一個 jackson class 的實現,它動態序列化作為“文本 map 密鑰”傳遞的所有內容,並用 @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 
      }

   } 

如果您的目標是斷言只接受帶注釋的類,那么您幾乎沒有解決方法:

  1. 編寫一個在編譯時執行斷言的注釋處理器(查看 @NonNull 等如何工作)。 這是一項有趣的工作,但並非微不足道,因為編譯/類型系統對於許多經驗豐富的 Java 開發人員來說是全新的。
  2. 使用某種形式的 AOP(AspectJ、Spring AOP 等)來“建議”所有帶注釋的方法,其職責是聲明參數具有相同的注釋。
  3. 使用parameter.getClass().isAnnotationPresent(MyAnnotation.class)在運行時顯式檢查

Checker Framework之類的工具插入到編譯器中,以類似於您要求的方式限制通用實例化。 它被實現為注解處理器,並提供正確使用的編譯時保證。

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

Checker 框架使您能夠構建自己的檢查器,它可以強制執行您喜歡的有關@KeySerializable的任何規則。 在您的情況下,規則可能非常簡單,您只需定義幾個類型限定符並使用子類型檢查器——至少一開始是這樣。

請注意,要使 Checker Framework 使用@KeySerializable注釋工作,該注釋必須是類型注釋而不是聲明注釋。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM