Reputation: 4942
In java it is possible to bound the generic parameter to classes implementing specific interface, so following is possible
interface MyInterface {}
class MyClassA implements MyInterface {}
class MyBoundedClassA<T extends MyInterface>
Now what if instead the interface I would like to bound the parameter to class annotated with specific annotation, like:
interface @MyAnnotation {}
@MyAnnotation
class MyClassB {}
class MyBoundedClassB<T extends MyAnnotation> // NOT possible
Is it possible to achieve such a behavoiur in Java?
---- EDIT
On request adding real world example. Slighly modifying the domain to make the example more understandable.
There is well known jackson library for serializing objects. This library does not support serialization of map keys other than Strings, so following is not possible out of the box
class TimeRange {
LocalDateTime startDate;
LocalDateTime endDate;
}
class SportsmenActivities {
private Map<String, <TimeRange, List<Activity>> sportActivities;
}
In this example the key of outer map is "sportsmanCode" liek "andy", "mike", "john" .Inner Map contains activities performed by given sportsman within given period.
So let's say Andy, was jogging for one day than the entry would be:
new SportsmanActivities().get("andy").put(TimeRange.of('2012-12-01,'2012-12-02'), List.with(new JoggingActivity)) // did some pseudo code here for readablity
Now as said Jackson will not serialize that out of the box, so I wrote generic module which allows serialization of such complex map.
To use that what you need to do is to annotate your "key" class like that:
@KeySerializable
class TimeRange {
@MyMapKey
LocalDateTime startDate;
@MyMapKey
LocalDateTime endDate;
}
As you can guess fields annotated with @MyMapKey will be used to generate MapKey.
Now I have a implementation of jackson class which dynamically serializes everything passed as a "text map key" annotated with @KeySerializable. The signature is follwing
class MyMapKeySerializer<T> extends JsonSerializer<T> {
serialize (T keyToSerialize) {
// do magic
}
}
This works, but I would like to limit T to only accept classes annotated with @KeySerializable, as only for such classes this method makes sense. Ideally this would be something like:
class MyMapKeySerializer<T annotatedWith @KeySerializable> extends JsonSerializer<T> {
serialize (T keyToSerialize) {
// do magic
}
}
Upvotes: 0
Views: 2766
Reputation: 8117
A tool like the Checker Framework plugs into a compiler to restrict generic instantiation in a way similar to what you requested. It is implemented as an annotation processor, and it gives a compile-time guarantee of correct use.
For example, you can write class MyList<T extends @NonNull Object> {...}
.
The Checker Framework enables you to build your own checker, which enforces any rules you like about @KeySerializable
. In your case, the rules might be so simple that you can just define a couple of type qualifiers and use the Subtyping Checker -- at least at first.
Note that for the Checker Framework to work using the @KeySerializable
annotation, that annotation must be a type annotation rather than a declaration annotation.
Upvotes: 1
Reputation: 3081
If your goal is to assert only annotated classes are accepted then you have few workaround options:
parameter.getClass().isAnnotationPresent(MyAnnotation.class)
Upvotes: 4