致自己:Java学习笔记之注解

注解

一、注解的作用

1、编写文档:通过代码里标识的元数据生成文档。

2、代码分析:通过代码里标识的元数据对代码进行分析。

3、编译检查:通过代码里标识的元数据让编译器能实现基本的编译检查。

二、基本内置注解

1、@Override

1.1、实现编译时检查,你可以为你的方法添加该注解,以声明该方法用于覆盖父类中的方法,如果该方法不是覆盖父类中的方法,将会在编译时报错。

1.2、代码示例

/*
关于JDK lang包下的Override注解
源代码:
public @interface Override {
}

标识性注解,给编译器做参考的。
编译器看到方法上有这个注解的时候,编译器会自动检查该方法是否重写了父类的方法。
如果没有重写,报错。

这个注解只是在编译阶段起作用,和运行期无关!

 */

// @Override这个注解只能注解方法。
// @Override这个注解是给编译器参考的,和运行阶段没有关系。
// 凡是java中的方法带有这个注解的,编译器都会进行编译检查,如果这个方法不是重写父类的方法,编译器报错。

//@Override
public class AnnotationTest02 {

    //@Override
    private int no;

    @Override
    public String toString() {
        return "toString";
    }

}
2、@Deprecated

2.1、对不应该在使用的方法添加注释, 当编程人员使用这些方法时, 将会在编译时显示提示信息,它与 javadoc 里的 @deprecated 标记有相同的功能。

2.2、代码示例

// 表示这个类已过时。
@Deprecated
public class AnnotationTest03 {

    @Deprecated
    private String s;

    public static void main(String[] args) {
        AnnotationTest03 at = new AnnotationTest03();
        at.doSome();
    }

    @Deprecated
    public void doSome(){
        System.out.println("do something!");
    }

    // Deprecated这个注解标注的元素已过时。
    // 这个注解主要是向其它程序员传达一个信息,告知已过时,有更好的解决方案存在。
    @Deprecated
    public static void doOther(){
        System.out.println("do other...");
    }
}

class T {
    public static void main(String[] args) {
        AnnotationTest03 at = new AnnotationTest03();
        at.doSome();

        AnnotationTest03.doOther();

        try {
            Class c = Class.forName("java.util.Date");
            Object obj = c.newInstance();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
3、@SuppressWarnings

3.1、与前两个注释有所不同,你需要添加一个参数才能正确使用,这些参数值都是已经定义好了的,我们选择性的使用就好了

3.2、参数说明:

参数说明
deprecation使用了过时的类或方法时的警告
unchecked执行了未检查的转换时的警告,比如当使用集合时没有使用泛型来指定集合保存的类型
fallthrough当switch程序直接通往下一种情况而没有break时的警告
path在类路径、源文件路径中有不存在的路径时的警告
serial当在可序列化的类上缺少 serialVersionUID 定义时的警告
finally任何 finally 子句不能正常完成时的警告
all关于以上所有情况的警告
rawtypes忽略传参时没有指定泛型的警告

三、自定义注解

1、使用@interface自定义注解

1.1、自定义注解代码示例

package annotation;

//自定义注解
public @interface MyAnnotation {
    //???
}
package annotation;

// 注解修饰注解。
@MyAnnotation
public @interface OtherAnnotation {
	//???
}
2、自定义注解的使用

2.1、默认情况下。注解可以出现在任意位置

package annotation;

//默认情况下注解可以出现在任意位置

@MyAnnotation
public class AnnotationTest1 {
    @MyAnnotation
    private int num;

    @MyAnnotation
    public AnnotationTest1() {

    }

    public static void test() {
        @MyAnnotation
        int a = 10;
    }

    public static void test2(@MyAnnotation
                             String  naem,
                             @MyAnnotation
                             int age) {

    }
}
@MyAnnotation
interface MyInterface {

}
@MyAnnotation
enum Season {
    SPRING,SUMMER,AUTUMN,WINTER
}
3、自定义注解添加变量

3.1、自定义注解也可以添加变量,变量类型只能是基本数据类型、String类型、Class类型、枚举类型、数组类型,并且参数不能为空。

package annotation2;

public @interface MyAnnotation {
    //添加属性
    String name();
}
package annotation2;

/*
    @MyAnnotation:只添加这个,程序报错
    如果一个注解中有属性,那么注解时必须给
    这个属性赋值,除非该属性指定了默认值
    @MyAnnotation(属性名=属性值,属性名=属性值,属性名=属性值)
 */
public class AnnotationTest1 {
    @MyAnnotation(name = "jack")
    public void doSome() {

    }
}

3.2、如果一个注解中只有一个属性,并且该属性名字为value,则使用该注解的时候,属性名可以省略

package annotation2;

public @interface MyAnnotation {
    //添加一个value属性
    String value();
}
package annotation2;

public class AnnotationTest1 {
    @MyAnnotation(value = "jack")
    public void doSome() {

    }
    //如果一个注解中只有一个属性,并且名字为value,使用时可以省略属性名
    @MyAnnotation("jack")
    public void doOther() {

    }
}

3.3、为注解赋默认值

package annotation2;

public @interface MyAnnotation {
    //添加属性,并赋予默认值
    String name();
    int age() default 20;
}
package annotation2;

public class AnnotationTest1 {
    //注解有默认值值时,使用注解时可以重新赋值,也可以不赋值,使用默认值
    @MyAnnotation(name = "jack")
    public void doSome() {

    }
    @MyAnnotation(name = "mark", age = 18)
    public void doOther() {

    }
}

四、注解的属性类型

1、注解中的属性类型

1.1、注解中的属性类型可以是byte、short、int、long、float、double、boolean、char、String、Class、枚举类型,及以上每一种类型的数组类型

public @interface MyAnnotation {
    /*
    注解当中的属性可以是哪一种类型?
    属性的类型可以是:
		byte short int long float double boolean char String Class 枚		举类型以及以上每一种的数组形式。
     */
    int value1();

    String value2();

    int[] value3();

    String[] value4();

    Season value5();

    Season[] value6();

    Class parameterType();

    Class[] parameterTypes();
}

1.2、测试案例

//定义枚举Season
public enum Season {
    SPRING,SUMMER,AUTUMN,WINTER
}
public @interface OtherAnnotation {
    //年龄属性
    int age();
    //邮箱属性
    String[] email();
    //季节属性,Season是枚举类型
    Season[] arr();
}
public class OtherAnnotationTest {
    //数组使用大括号括起来
    @OtherAnnotation(age=18,email={"zs@qq.com","lisi@qq.com"},arr={Season.SPRING,Season.AUTUMN})
    public void doSome() {

    }
    //当数组中只有一个元素时,大括号可以省略
    @OtherAnnotation(age=20,email="zs@qq.com",arr=Season.WINTER)
    public void doOther() {
        
    }
}

五、元注解

1、@Target注解

1.1、当我们的自定义注释不断的增多也比较复杂时,就会导致有些开发人员使用错误。为此,Java 提供了一个ElementType枚举类型来控制每个注释的使用范围,比如说某些注释只能用于普通方法,而不能用于构造函数等

//源代码
package java.lang.annotation;
    public enum ElementType {
    TYPE,/** Class, interface (including annotation type), or enum
    declaration */
    FIELD,/** Field declaration (includes enum constants) */
    METHOD,/** Method declaration */
    PARAMETER,/** Parameter declaration */
    CONSTRUCTOR,/** Constructor declaration */
    LOCAL_VARIABLE,/** Local variable declaration */
    ANNOTATION_TYPE,/** Annotation type declaration */
    PACKAGE /** Package declaration */
}
参数使用范围
TYPE适用于class、interface、enum
FIELD适用于field
METHOD适用于method
PARAMETER适用于parameter
CONSTRUCTOR适用于constructor
LOCAL_VARIABLE适用于局部变量
ANNOTATION_TYPE适用于annotation类型
PACKAGE适用于package

1.2、测试案例

package annotation3;

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

//只允许该注解可以标注类和方法
@Target({ElementType.TYPE,ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface MyAnnotation {
    //value属性
    String value() default "好好学习";
}
package annotation3;

@MyAnnotation("天天向上")
public class MyAnnotationTest {
    /*
    属性和构造方法不能使用该注解,报错
        @MyAnnotation
        int i = 0;
        @MyAnnotation
        public MyAnnotation() {

        }
    */

    @MyAnnotation
    public void doSome() {

    }
}
package annotation3;

public class ReflectAnnotationTest {
    public static void main(String[] args) throws ClassNotFoundException {
        //获取这个类
        Class c = Class.forName("annotation3.MyAnnotationTest");
        //判断这个类上面有没有@MyAnnotation
        System.out.println(c.isAnnotationPresent(MyAnnotation.class)); //true
        if (c.isAnnotationPresent(MyAnnotation.class)) {
            //获取注解对象
            MyAnnotation myAnnotation = (MyAnnotation) c.getAnnotation(MyAnnotation.class);
            //类上面的注解对象:@annotation3.MyAnnotation(value="天天向上")
            System.out.println("类上面的注解对象:" + myAnnotation);
            //获取注解对象的属性,和调用接口一样
            String value = myAnnotation.value();
            System.out.println("注解对象的属性:" + value); //注解对象的属性:天天向上
        }
        //判断String类上面是否存在这个注解
        Class str = Class.forName("java.lang.String");
        System.out.println(str.isAnnotationPresent(MyAnnotation.class));
    }
}

2、@Retention注解

2.1、源码说明

//原码
package java.lang.annotation;
public enum RetentionPolicy {
    /*
    * Annotations are to be discarded by the compiler.
    */
    SOURCE,
    /**
    * Annotations are to be recorded in the class file by the compiler
    * but need not be retained by the VM at run time. This is the default
    * behavior.
    */
    CLASS,
    /**
    * Annotations are to be recorded in the class file by the compiler
    and
    * retained by the VM at run time, so they may be read reflectively.
    */
    RUNTIME
}

2.2、参数说明

参数说明
RetentionPolicy.SOURCE编译器使用后,直接丢弃这种策略的注释
RetentionPolicy.CLASS编译器将把注解记录在 class 文件中. 当运行 Java 程序时, JVM 不会保留注解。 这是默认值
RetentionPolicy.RUNTIME编译器将把注解记录在 class 文件中. 当运行 Java 程序时, JVM 会保留注解. 程序可以通过反射获取该注解
3、@Documented注解

3.1、Java 提供的Documented 元注释跟 Javadoc 的作用是差不多的,其实它存在的好处是开发人员可以定制Javadoc 不支持的文档属性,并在开发中应用。如果你要使用@Documented 元注释,你就得为该注释设置 RetentionPolicy.RUNTIME 保持性策略。

4、@Inherited注解

4.1、控制注释是否会影响到子类

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值