IntersectionType
January 22, 2014 Leave a comment
I came across this code that uses a cast to assign a Lambda expression to a marker interface in Angelika Langer’s explanation.
Serializable f2 = (BiPredicate<String,String> & Serializable) (s,t) -> s.equalsIgnoreCase(t);
As I was curious about this I tried to detect an intersection type (T extends String & @IntersectionType.TypeUse(value = 2) Serializable) and print the annotation applied on one of its bounds.
The result is
Annotation [] [com.test.IntersectionType.Test] Annotation [[]] [java.lang.String] Annotation [[]] [java.io.Serializable]
This could be a JDK 8 bug at this time. I am getting nothing.
I am using
java version "1.8.0-ea"
Java(TM) SE Runtime Environment (build 1.8.0-ea-b123)
Java HotSpot(TM) 64-Bit Server VM (build 25.0-b65, mixed mode)
I presumed there is a javax.lang.model.type.IntersectionType that will match T extends String & Serializable. So I though there is a TypeMirror that I can check for that type. But it does not seem so.
I will update later when I get a proper result.
Update : The method is updated and it works partly. I am getting the intersection type. But I think one cannot get the annotation type of the intersection type directly because the annotation is applied on each of the bounds separately. So the old code(see the comments below) is sufficient but now the returned array is empty which could mean that this is a bug in itself.
Annotation [] [com.test.IntersectionType.Test]
Annotation [[]] [java.lang.String&java.io.Serializable]
Annotation [[]] [java.lang.String]
Annotation [[]] [java.io.Serializable]
public class IntersectionType { @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.TYPE_USE) public @interface TypeUses { TypeUse[] value(); } @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.TYPE_USE) @Repeatable(TypeUses.class) protected @interface TypeUse { int value(); } //Intersection type class Test<T extends String & @IntersectionType.TypeUse(value = 2) Serializable>{ } }
Processor method
private void processClassTypeParameters(Element e) { for (TypeParameterElement typeParameterElement : ((TypeElement) e).getTypeParameters()) { for( AnnotationMirror am : typeParameterElement.getAnnotationMirrors() ){ System.out.println( "Annotation [" + am + "] [" + typeParameterElement + "]"); } //Get the intersection type TypeVariable tv = (TypeVariable)typeParameterElement.asType(); TypeMirror tm = tv.getUpperBound(); //This may not return anything.(See explanation above) System.out.println( "Annotation [" + Arrays.asList( tm.getAnnotationsByType(com.test.IntersectionType.TypeUse.class)) + "] [" + tm + "]"); for (TypeMirror typeMirror : typeParameterElement.getBounds()) { //Commented section is not the right way //if( typeMirror instanceof javax.lang.model.type.IntersectionType) { //The following line returns an empty array most probably due to a different bug. System.out.println( "Annotation [" + Arrays.asList(typeMirror.getAnnotationsByType(com.test.IntersectionType.TypeUse.class)) + "] [" + typeMirror + "]"); //} } } }