高频面试八股文用法篇(七) Java注解及其作用

目录

什么是注解?

注解的作用?

注解的类型

元注解

Java自带/预定义的注解

自定义注解

什么是自定义注解?


什么是注解?

它是JDK1.5及以后版本引入的一个特性,与类、接口、枚举是在同一个层次。它可以声明在包、类、字段、方法、局部变量、方法参数等的前面,用来对这些元素进行说明,注释。

Java注解是附加在代码中的一些元信息,用于一些工具在编译、运行时进行解析和使用,起到说明、配置的功能,注解相关类都包含在java.lang.annotation包中。

注解给谁用?给编译器、给解析程序用。

ps: 注解区别于注释,注释是文字描述的,给程序员看的。

注解的作用?

  • 编写文档:通过代码里标识的注解生成文档【生成文档doc文档】
  • 代码分析:通过代码里标识的注解对代码进行分析【使用反射】
  • 编译检查:通过代码里标识的注解让编译器能够实现基本的编译检查【Override】

注解的类型

元注解

用于定义注解的注解,包括@Retention(标明注解被保留的阶段)、@Target(标明注解使用的范围)、@Inherited(标明注解可继承)、@Documented(标明是否生成javadoc文档)


@Retention:定义注解的保留策略
@Retention(RetentionPolicy.SOURCE)             //注解仅存在于源码中,在class字节码文件中不包含
@Retention(RetentionPolicy.CLASS)              //默认的保留策略,注解会在class字节码文件中存在,但运行时无法获得,
@Retention(RetentionPolicy.RUNTIME)            //注解会在class字节码文件中存在,在运行时可以通过反射获取到
 
@Target:指定被修饰的Annotation可以放置的位置(被修饰的目标)
@Target(ElementType.TYPE)                      //接口、类
@Target(ElementType.FIELD)                     //属性
@Target(ElementType.METHOD)                    //方法
@Target(ElementType.PARAMETER)                 //方法参数
@Target(ElementType.CONSTRUCTOR)               //构造函数
@Target(ElementType.LOCAL_VARIABLE)            //局部变量
@Target(ElementType.ANNOTATION_TYPE)           //注解
@Target(ElementType.PACKAGE)                   //包
注:可以指定多个位置,例如:
@Target({ElementType.METHOD, ElementType.TYPE}),也就是此注解可以在方法和类上面使用
 
@Inherited:指定被修饰的Annotation将具有继承性
 
@Documented:指定被修饰的该Annotation可以被javadoc工具提取成文档

Java自带/预定义的注解

@Override:检测被该注解标注的方法是否是继承自父类(接口)的

@Deprecated:该注解标注的内容,表示已过时

@SuppressWarnings:压制警告

自定义注解

可以根据自己的需求定义注解。

什么是自定义注解?

  • 格式
元注解
public @interface 注解名称{
        属性列表;
}

注解本质上就是一个接口,该接口默认继承Annotation接口

  • 举例
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

//@Documented – 注解是否将包含在JavaDoc中
//@Retention – 什么时候使用该注解
//@Target – 注解用于什么地方
//@Inherited – 是否允许子类继承该注解

1。 定义注解
@Target(ElementType.METHOD)//作用目标是方法
@Retention(RetentionPolicy.RUNTIME)//保留策略使用RUNTIME:注解会在class字节码文件中存在,在运行时可以通过反射获取到
public @interface MyAnnotationTest {
    String name() default "hello";
}

2. 注解处理器
public class ReflectProcessor {
    public void parseMethod(final Class<?> clazz) throws Exception {
        final Object obj = clazz.getConstructor(new Class[] {}).newInstance(new Object[] {});
        final Method[] methods = clazz.getDeclaredMethods();
        for (final Method method : methods) {
            final MyAnnotationTest myAnnotationTest = method.getAnnotation(MyAnnotationTest.class);
            if (null != my) {
                System.out.println("方法名:");
                System.out.println(method.getName());
                method.invoke(obj, my.name());
            }
        }
    }
}


3. 测试一下注解
public class ReflectTest {
   @MyAnnotationTest
    public static void sayHello1(final String name) {
        System.out.println("Hi, " + name);
    }

/** 输出结果
方法名:
sayHello1
Hi, hello
*/
    @MyAnnotationTest(name = "kuaile")
    public static void sayHello2(final String name) {
        System.out.println("Hi, " + name);
    }
/** 输出结果
方法名:
sayHello2
Hi, kuaile
*/

    public static void main(final String[] args) throws Exception {
        final ReflectProcessor reflectProcessor = new ReflectProcessor();
        reflectProcessor.parseMethod(ReflectTest.class);
    }

}

@Retention – 定义该注解的生命周期

● RetentionPolicy.SOURCE : 在编译阶段丢弃。这些注解在编译结束之后 就不再有任何意义,所以它们不会写入字节码。@Override, @SuppressWarnings都属于这类注解。
● RetentionPolicy.CLASS : 在类加载的时候丢弃。在字节码文件的处理中有用。注解默认使用这种方式
● RetentionPolicy.RUNTIME : 始终不会丢弃,运行期也保留该注解,因此可以使用反射机制读取该注解的信息。我们自定义的注解通常使用这种方式。

Target – 表示该注解用于什么地方。默认值为任何元素,表示该注解用于什么地方。可用的ElementType 参数包括

● ElementType.CONSTRUCTOR: 用于描述构造器
● ElementType.FIELD: 成员变量、对象、属性(包括enum实例)
● ElementType.LOCAL_VARIABLE: 用于描述局部变量
● ElementType.METHOD: 用于描述方法
● ElementType.PACKAGE: 用于描述包
● ElementType.PARAMETER: 用于描述参数
● ElementType.TYPE: 用于描述类、接口(包括注解类型) 或enum声明

猜你喜欢

转载自blog.csdn.net/wodeyijia911/article/details/131064830