Java学习笔记----注解

 

一、注解是什么?

注释大家都知道,就是对程序起解释说明作用的,而注解同样是对程序起解释说明作用的,只不过注释是给人看的,而注解是给计算机看的。

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

二、预定义注解

预定义注解就是Java中已经定义好的注解,比如@Override。

几个常用的预定义注解:

1.@Override:检测该注解修饰的方法是否是继承自父类(接口);

2.@Deprecated:表示该注解修饰的内容是已过时的;

Java学习笔记----注解_第1张图片

3.@SuppressWarnings:压制警告,忽略警告,一般传递参数“all”,@SuppressWarnings("all"),并且放在类上面,压制整个类的所有警告,

也可以放在特定的位置指定要忽略的警告,@SuppressWarnings({"uncheck","指定警告"})

比如下图,放在mid()方法上,压制mid()方法中的已过时警告;

Java学习笔记----注解_第2张图片

三、自定义注解和元注解

 

1.元注解

在Java中我们可以自己定义注解,在自定义注解时,需要涉及到元注解,元注解是什么呢?元注解就是用于描述注解的注解。

四种元注解:

1.@Target:用来描述注解能够作用的位置。

(1) @Target(ElementType.TYPE):修饰的注解只能作用于类上

(2) @Target(ElementType.METHOD):修饰的注解只能作用于方法上

(3) @Target(ElementType.FIELD):修饰的注解只能作用于字段上

注意:当注解未指定Target时,注解可以作用于任何元素上。多个值使用{ }包含并用都好隔开。如下:

@Target(value={CONSTRUCTOR, FIELD, LOCAL_VARIABLE, METHOD, PACKAGE, PARAMETER, TYPE})

2.@Retention:描述注解被保留的阶段,用来约束注解的生命周期。

(1)@Rentention(RetentionPolicy.SOURCE):当前注解在源码编译之前就会被编译器抛弃(源码时期);

(2)@Rentention(RetentionPolicy.CLASS):当前注解可以保留到编译期,在class文件中可用,但在加载进内存之前就会被JVM丢弃(编译时期);

(3)@Rentention(RetentionPolicy.RUNTIME):当前注解可以保留到运行期,即保留到class字节码文件并可以被JVM读取到,因此可以通过反射机制获取到该注解的信息(运行时期);

注意:当注解未指定Rentention值时,默认值是CLASS;

3.@Documented:描述注解是否被抽取到api文档中。

示例:

定义两个注解如下:

@Documented
public @interface MyAnno01 {
    
}

public @interface MyAnno02 {

}

在类中使用这两个注解:

​
public class Anno01 {

    public static void main(String[] args) {
        @MyAnno01
        @MyAnno02
        public void big(){
            System.out.println("Test...");
        }
    }

}

将上面java文件(Anno01.java、MyAnno01.java、MyAnno02.java)放到一个文件夹中,

win+R打开cmd,然后在cmd中打开上面这个java文件所在文件夹,输入javadoc指令+空格+类名,如下:

C:\Users\Administrator\Desktop\xinjian>javadoc Anno01.java

之后回车即可生成api文档。

在文件中打开生成的index.html,可以发现

Java学习笔记----注解_第3张图片

只有@MyAnno01注解被保留到api文档中,而@MyAnno02注解则没有。

4.@Inherited:可以让注解被继承,但这并不是真的继承,只是通过使用@Inherited,可以让子类Class对象使用getAnnotations()获取父类被@Inherited修饰的注解。

当然,要通过此方法获取注解信息,@Inherited修饰的注解必须被@Rentention(RetentionPolicy.RUNTIME)修饰。

(注意:注解本身是不支持继承的)

//定义注解
@Inherited
@Documented
@Retention(RetentionPolicy.RUNTIME)
public @interface MyAnno01 {


}

//使用注解
@MyAnno01
class Mid{

}

//创建子类
class Small extends Mid{

}

public class Big {

    public static void main(String[] args) {
        Mid mid=new Small();
        System.out.println(Arrays.toString(mid.getClass().getAnnotations()));
        /*
        运行结果:[@cn.Hello.MyAnno01()]
         */
    }

}

 

2.自定义注解

自定义注解的格式为:

元注解

public @interface 注解名称 {

属性列表;

}

属性列表:接口中可以定义的抽象方法。

要求:

属性的返回值类型有下列取值:

  • 基本数据类型
  • String
  • 枚举
  • 注解
  • 以上类型的数组

定义了属性,在使用时需要给属性赋值。

  1. 如果定义属性时,使用default关键字给属性值默认初始值,则使用注解时,可以不进行属性的赋值;
  2. 如果只有一个属性需要赋值,且该属性名称为value,则value可以省略,直接定义即可;
  3. 数组赋值时,值使用{ }包裹,如果数组只有一个值,则{ }可以省略。

比如:

@MyAnno01(num={1,2,3})

四、在程序中使用(解析)注解

在程序中使用(解析)注解:获取注解中定义的属性值,

步骤:

  1. 创建注解修饰元素的类对象;
  2. 用类对象调用getAnnotation()方法获取注解对象;
  3. 调用注解中的抽象方法,获取配置的属性值。

案例如下:

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

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface Pro {

    String className();
    String methodName();

}


import java.lang.annotation.Annotation;
import java.lang.reflect.Method;

/*
    创建一个“框架”类,可以创建任意类的对象,执行任意类中的方法
    只需改动注解中的类名和方法名即可实现。
 */
@Pro(className = "cn._17_Annotation.Worker",methodName = "work")
public class ReflectTestPro {

    public static void main(String[] args) throws Exception {
        
        //解析注解:获取注解中定义的属性值
        //1.创建注解修饰元素的类对象
        Class proClass = ReflectTestPro.class;
        //2.用类对象调用getAnnotation()方法获取注解对象
        Pro anno = proClass.getAnnotation(Pro.class);
        //3.调用注解中的抽象方法,获取配置的属性值
        String className = anno.className();
        String methodName = anno.methodName();
        
        //通过反射机制创建对象调用方法
        Class cls = Class.forName(className);
        Object obj = cls.newInstance();
        Method method = cls.getMethod(methodName);
        method.invoke(obj);

    }

}

五、总结

注解是放在Java源码的类、方法、字段、参数前的一种特殊“注释”

注解的作用:

  • 通过代码里标识的注解生成帮助文档;
  • 通过代码里标识的注解让编译器能够实现基本的编译检查;(例如:@Override修饰的方法如果不是继承自父类/接口,就会产生异常)
  • 可以在反射中解析并使用Annotation。


 

 

 

你可能感兴趣的:(java笔记,java)