Java 8:从类到注释类型的转换

15

在Java 8中,Class似乎已经拥有了获取其超类和超接口的AnnotatedType视图方法。

如何将Class转换为自己的自身的AnnotatedType? 这个问题甚至有意义吗?

据我所知,AnnotatedType具有 Type ,而非是 Type 。虽然它是一个AnnotatedElement,但整个过程非常混乱。

到目前为止,我已经在Javadocs中搜索了很久,但没有发现相关信息。


+1 有趣的问题。 - Simon Dorociak
我认为我已经弄清楚了这是无意义的:可以注释类型的用法,但类型本身不能被注释。 - Louis Wasserman
我仍在努力弄清楚类型的注释用法以及它如何应用于 getAnnotatedSuperclass() - Sotirios Delimanolis
2个回答

11

所以我最终对AnnotatedType接口有了可接受的理解。这里有一个工作的Java 8示例,用于说明它的用途之一。

public static void main(String[] args) {
    Class<?> fooClass = Foo.class;
    AnnotatedType type = fooClass.getAnnotatedSuperclass();
    System.out.println(type);
    System.out.println(Bar.class == type.getType());
    System.out.println(Arrays.toString(type.getAnnotations()));
    System.out.println(Arrays.toString(type.getDeclaredAnnotations()));
}

public static class Bar {
}

public static class Foo extends @Custom Bar {
}

// So that annotation metadata is available at run time
@Retention(RetentionPolicy.RUNTIME)
// TYPE_USE being the important one
@Target(value = {ANNOTATION_TYPE, CONSTRUCTOR, FIELD, LOCAL_VARIABLE,
        METHOD, PACKAGE, PARAMETER, TYPE, TYPE_PARAMETER, TYPE_USE}) 
public @interface Custom {
}

这将打印内容

sun.reflect.annotation.AnnotatedTypeFactory$AnnotatedTypeBaseImpl@1d44bcfa
true
[@com.testing.Test$Custom()]
[@com.testing.Test$Custom()]

AnnotatedType接口表明:

AnnotatedType表示当前虚拟机中运行的程序中,类型的潜在带注释使用。

Class#getAnnotatedSuperclass() javadoc表明:

返回一个AnnotatedType对象,该对象表示用于指定此Class对象表示的实体的超类的类型使用。

我在AnnotatedType javadoc中加粗了“potentially”,因为它清楚地表明类型使用不一定要带注释。如果你有

public static class Bar {}
...
Bar.class.getAnnotatedSuperclass(); // returns Class instance for java.lang.Object

这是一个在Java 7及以下版本中无法实现的用例,因为您无法注释类型使用情况(在此处查看一些示例)。然而,在Java 8中,您可以这样做。

public static class Foo extends @Custom Bar {

其中类型Bar被用作超类,并且其使用被注释为@Custom。因此,它是一个AnnotatedType。因此,Foo.class.getAnnotatedSuperClass()将返回一个AnnotatedType实例来表示这种用法。

如何将Class转换为其自身的AnnotatedType?这个问题有意义吗?

这个问题没有意义。这是因为Class对象包含了关于一个类的自包含元数据。所谓自包含是指可以从类的.class文件(或实际声明)中推导出的所有内容。你无法推导出该类型在其他地方的任何用法,因此它不能转换为任何AnnotatedType以表示它自己。

您可以拥有

public static class Foo extends @Custom Bar {}

public static class Zoom extends @Custom Bar {}

public static class Doing extends @Custom Bar {}

以上每种对于Bar的使用都有一个AnnotatedType实例,但是你会选择哪一个将[Bar]Class转换为其自身的AnnotatedType呢?


哇!你比我先发了一个例子。不过还是给你点赞!:-) - Stuart Marks
1
请注意@Retention(RetentionPolicy.RUNTIME)同样很重要。如果省略它,示例将无法正常工作。 - Stuart Marks

2
下面是一个简单的示例,展示了getAnnotatedSuperclass()的用法:
import java.lang.annotation.*;

public class AnnotationTest {

    @Target(ElementType.TYPE_USE)
    @Retention(RetentionPolicy.RUNTIME)
    @interface First { }

    @Target(ElementType.TYPE_USE)
    @Retention(RetentionPolicy.RUNTIME)
    @interface Second { }

    class A { }

    class B extends @First @Second A { }

    public static void main(String[] args) {
        Annotation[] anns = B.class.getAnnotatedSuperclass().getAnnotations();
        System.out.printf("There are %d annotations on B's use of its superclass.%n", anns.length);
        for (Annotation a : anns)
            System.out.println(a.annotationType().getName());
    }
}

这个程序的输出结果是:
There are 2 annotations on B's use of its superclass.
AnnotationTest$First
AnnotationTest$Second

注意注解出现在B的超类(即A)的使用时与A本身的声明不同。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接