首页后端开发JAVAJava 基础 - 注解机制详解(二)

Java 基础 - 注解机制详解(二)

时间2023-07-14 11:50:02发布访客分类JAVA浏览1404
导读:元注解 - @DocumentedDocumented注解的作用是:描述在使用 javadoc 工具为类生成帮助文档时是否要保留其注解信息。以下代码在使用Javadoc工具可以生成@TestDocAnn​otation注解信息。import...

元注解 - @Documented

Documented注解的作用是:描述在使用 javadoc 工具为类生成帮助文档时是否要保留其注解信息。

以下代码在使用Javadoc工具可以生成@TestDocAnn​otation注解信息。

import java.lang.annotation.Documented;
    
import java.lang.annotation.ElementType;
    
import java.lang.annotation.Target;

 
@Documented
@Target({
ElementType.TYPE,ElementType.METHOD}
)
public @interface TestDocAnnotation {
    
 
    public String value() default "default";

}
    

元注解 - @Inherited

Inherited注解的作用:被它修饰的Annotation将具有继承性。如果某个类使用了被@Inherited修饰的Annotation,则其子类将自动具有该注解。

我们来测试下这个注解:

  • 定义@Inherited注解:
@Inherited
@Retention(RetentionPolicy.RUNTIME)
@Target({
ElementType.TYPE,ElementType.METHOD}
)
public @interface TestInheritedAnnotation {
    
    String [] values();
    
    int number();

}
    

使用这个注解

@TestInheritedAnnotation(values = {
"value"}
, number = 10)
public class Person {

}


class Student extends Person{

    @Test
    public void test(){
    
        Class clazz = Student.class;
    
        Annotation[] annotations = clazz.getAnnotations();

        for (Annotation annotation : annotations) {
    
            System.out.println(annotation.toString());

        }

    }

}
    

输出

xxxxxxx.TestInheritedAnnotation(values=[value], number=10)


1


即使Student类没有显示地被注解@TestInheritedAnnotation,但是它的父类Person被注解,而且@TestInheritedAnnotation被@Inherited注解,因此Student类自动有了该注解。


元注解 - @Repeatable (Java8)

@Repeatable请参考Java 8 - 重复注解


元注解 - @Native (Java8)

使用 @Native 注解修饰成员变量,则表示这个变量可以被本地代码引用,常常被代码生成工具使用。对于 @Native 注解不常使用,了解即可


注解与反射接口

定义注解后,如何获取注解中的内容呢?反射包java.lang.reflect下的AnnotatedElement接口提供这些方法。这里注意:只有注解被定义为RUNTIME后,该注解才能是运行时可见,当class文件被装载时被保存在class文件中的Annotation才会被虚拟机读取。


AnnotatedElement 接口是所有程序元素(Class、Method和Constructor)的父接口,所以程序通过反射获取了某个类的AnnotatedElement对象之后,程序就可以调用该对象的方法来访问Annotation信息。我们看下具体的先关接口


boolean isAnnotationPresent(Class?extends Annotation> annotationClass)

判断该程序元素上是否包含指定类型的注解,存在则返回true,否则返回false。注意:此方法会忽略注解对应的注解容器。


T extends Annotation> T getAnnotation(ClassT> annotationClass)

返回该程序元素上存在的、指定类型的注解,如果该类型注解不存在,则返回null。


Annotation[] getAnnotations()

返回该程序元素上存在的所有注解,若没有注解,返回长度为0的数组。


T extends Annotation> T[] getAnnotationsByType(ClassT> annotationClass)

返回该程序元素上存在的、指定类型的注解数组。没有注解对应类型的注解时,返回长度为0的数组。该方法的调用者可以随意修改返回的数组,而不会对其他调用者返回的数组产生任何影响。getAnnotationsByType方法与 getAnnotation的区别在于,getAnnotationsByType会检测注解对应的重复注解容器。若程序元素为类,当前类上找不到注解,且该注解为可继承的,则会去父类上检测对应的注解。


T extends Annotation> T getDeclaredAnnotation(ClassT> annotationClass)

返回直接存在于此元素上的所有注解。与此接口中的其他方法不同,该方法将忽略继承的注释。如果没有注释直接存在于此元素上,则返回null


T extends Annotation> T[] getDeclaredAnnotationsByType(ClassT> annotationClass)

返回直接存在于此元素上的所有注解。与此接口中的其他方法不同,该方法将忽略继承的注释


Annotation[] getDeclaredAnnotations()

返回直接存在于此元素上的所有注解及注解对应的重复注解容器。与此接口中的其他方法不同,该方法将忽略继承的注解。如果没有注释直接存在于此元素上,则返回长度为零的一个数组。该方法的调用者可以随意修改返回的数组,而不会对其他调用者返回的数组产生任何影响。


自定义注解

当我们理解了内置注解, 元注解和获取注解的反射接口后,我们便可以开始自定义注解了。这个例子我把上述的知识点全部融入进来, 代码很简单:


定义自己的注解

package com.pdai.java.annotation;
    

import java.lang.annotation.ElementType;
    
import java.lang.annotation.Retention;
    
import java.lang.annotation.RetentionPolicy;
    
import java.lang.annotation.Target;


@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface MyMethodAnnotation {
    

    public String title() default "";
    

    public String description() default "";


}
    
  

使用注解

package com.pdai.java.annotation;
    

import java.io.FileNotFoundException;
    
import java.lang.annotation.Annotation;
    
import java.lang.reflect.Method;
    
import java.util.ArrayList;
    
import java.util.List;


public class TestMethodAnnotation {


    @Override
    @MyMethodAnnotation(title = "toStringMethod", description = "override toString method")
    public String toString() {
    
        return "Override toString method";

    }


    @Deprecated
    @MyMethodAnnotation(title = "old static method", description = "deprecated old static method")
    public static void oldMethod() {
    
        System.out.println("old method, don't use it.");

    }


    @SuppressWarnings({
"unchecked", "deprecation"}
)
    @MyMethodAnnotation(title = "test method", description = "suppress warning static method")
    public static void genericsTest() throws FileNotFoundException {
    
        List l = new ArrayList();
    
        l.add("abc");
    
        oldMethod();

    }

}
    

用反射接口获取注解信息

在TestMethodAnnotation中添加Main方法进行测试:

public static void main(String[] args) {

    try {
    
        // 获取所有methods
        Method[] methods = TestMethodAnnotation.class.getClassLoader()
                .loadClass(("com.pdai.java.annotation.TestMethodAnnotation"))
                .getMethods();


        // 遍历
        for (Method method : methods) {

            // 方法上是否有MyMethodAnnotation注解
            if (method.isAnnotationPresent(MyMethodAnnotation.class)) {

                try {

                    // 获取并遍历方法上的所有注解
                    for (Annotation anno : method.getDeclaredAnnotations()) {
    
                        System.out.println("Annotation in Method '"
                                + method + "' : " + anno);

                    }
    

                    // 获取MyMethodAnnotation对象信息
                    MyMethodAnnotation methodAnno = method
                            .getAnnotation(MyMethodAnnotation.class);
    

                    System.out.println(methodAnno.title());


                }
 catch (Throwable ex) {
    
                    ex.printStackTrace();

                }

            }

        }

    }
 catch (SecurityException | ClassNotFoundException e) {
    
        e.printStackTrace();

    }

}
    

测试的输出

Annotation in Method 'public static void com.pdai.java.annotation.TestMethodAnnotation.oldMethod()' : @java.lang.Deprecated()
Annotation in Method 'public static void com.pdai.java.annotation.TestMethodAnnotation.oldMethod()' : @com.pdai.java.annotation.MyMethodAnnotation(title=old static method, description=deprecated old static method)
old static method
Annotation in Method 'public static void com.pdai.java.annotation.TestMethodAnnotation.genericsTest() throws java.io.FileNotFoundException' : @com.pdai.java.annotation.MyMethodAnnotation(title=test method, description=suppress warning static method)
test method
Annotation in Method 'public java.lang.String com.pdai.java.annotation.TestMethodAnnotation.toString()' : @com.pdai.java.annotation.MyMethodAnnotation(title=toStringMethod, description=override toString method)
toStringMethod

声明:本文内容由网友自发贡献,本站不承担相应法律责任。对本内容有异议或投诉,请联系2913721942#qq.com核实处理,我们将尽快回复您,谢谢合作!


若转载请注明出处: Java 基础 - 注解机制详解(二)
本文地址: https://pptw.com/jishu/309280.html
七日杀服务器什么配置好 java 异常类介绍

游客 回复需填写必要信息