注解的写法格式与作用

注解

一、注解的概述

1.1注解的概念
  • 注解是JDK1.5的新特性。
  • 注解相当一种标记,是类的组成部分,可以给类携带一些额外的信息。
  • 标记(注解)可以加在包,类,字段(成员变量),方法,方法参数以及局部变量上。
  • 注解是给机器(jvm)看的,编译器或JVM可以根据注解来完成对应的功能;而注释是给人(程序员)看的!
1.2注解的作用

注解的作用就是给程序带入参数。【替换xml配置文件】

  • JDK自带注解:
    @Override:用于标记方法重写!(在编译阶段对重写的方法进行语法检查,若父类没有这个方法,或者你重写的方法签名错误,那么在编译阶段会报错!)
    @SuppressWarnings:压制警告(防止在编码阶段,过多的警告,会影响程序员写代码的思路!)【后期投入使用的时候,需要将这个注解移除】
    @Deprecated:标记方法过时(可能处于安全考虑,更换新的方法用于取代这个方法,但是考虑到JDK升级的兼容性,依旧保留了之前的这个方法,只是不建议使用!)

二、自定义注解

1.1 注解的本质

我们观看@SuppressWarnings注解的源代码,发现注解其本质就是一个接口!

@Target({TYPE, FIELD, METHOD, PARAMETER, CONSTRUCTOR, LOCAL_VARIABLE})
@Retention(RetentionPolicy.SOURCE)
public @interface SuppressWarnings {
    String[] value(); // 注解的属性!
}
1.2 自定义注解格式
public @interface 注解名{
	// 里面定义属性即可!
}
1.3 注解的属性
* 属性定义的格式:
	格式1:数据类型 属性名();
	格式2:数据类型 属性名() default 默认值;

* 属性定义的示例:
        public @interface MyAnnotation {
            // 为注解定义属性
           包含属性:String value() ;//书名
        包含属性:double price()  ;//default 100价格,默认值为 100
        包含属性:String[] authors() ;//多位作者
        }
*  属性适用的数据类型
	* 八种数据数据类型(int,short,long,double,byte,char,boolean,float)
	* String,Class,注解类型,枚举类
	* 以上类型的一维数组形式
1.4 使用自定义注解(为注解的属性赋值)
* 普通属性:
	在使用注解的时候需要为注解的属性赋值!(定义注解属性给定的是什么类型的,那么使用的时候就给这个属性赋一个该类型的值)
* 特殊属性value:
	如果注解中只有一个属性且名字叫value,则在使用该注解时可以直接给该属性赋值,而不需要给出属性名。
	如果注解中除了value属性之外还有其他属性且只要有一个属性没有默认值,则在给属性赋值时value属性名也不能省略了。

* 小结:如果注解中只有一个属性时,一般都会将该属性名命名为value
/*
    注解使用:
        在方法上面添加自定义注解,然后为该注解的属性赋值!
 */
    // 使用自定义注解的时候,需要为自定义注解的属性赋值!
    @Book(value ="xxx", price = 68.0 , authors = {"传智播客","黑马程序员"})
    public void method(){
    }
}
// 若Book注解在定义的时候没有指定属性,那么使用这个注解的时候,不用为注解的属性赋值!
/*
① 若定义的注解中只有1个属性,而且属性的名字为value,那么在使用注解为属性赋值时,注解的属性名可以省略不写!(写上也不报错!)
*/
public @interface Book {
    // 为注解定义属性
    String value(); 
}

@Book("xxx")  // 此处可以写成 @Book(value="xxxx",还可以省略属性名称value不写 @Book("yyyy"))
public void method(){

}
/*
② 若定义的注解中只有1个属性,属性的名字为value,并且为value赋默认值了,那么在使用注解为属性赋值时可以不用为注解属性赋值
*/
public @interface Book {
    // 为注解定义属性
    String value() default "vip";	
}

@Book // 正确的!
public void method(){

}
//也可以这么干:
@Book(value="xxxx") // 正确的!
public void method(){
}
// 或者
@Book("xxxx") // 正确的!
public void method(){
}
1.5 为注解的属性赋值(各种类型演示)

自定义注解:

/*
    注解属性支持的数据类型有:
        * 八种数据数据类型(int,short,long,double,byte,char,boolean,float)
        * String,Class,注解类型,枚举类
        * 以上类型的一维数组形式
 */
public @interface itheima {

    // 基本类型
    char a();

    // 字符串类型
    String b();

    // Class类型
    Class c();

    // 注解类型
    MyAnnotation d();

    // 枚举类型
    Sex e();

    // 数组
    int[] f();

}

使用自定义注解(为注解的属性赋值):

/*
    使用自定义注解@itheima
 */
public class TestItheima {

    // 使用自定义注解,必须为注解的属性赋值!
    @itheima(a = 'A', b = "666", c = Test01.class, d = @MyAnnotation(value = {"xxx", "ooo"}), e = Sex.FatBoy, f = {10, 20})
    public void method() {

    }

}

三、 元注解

元注解:对注解进行修饰的注解就是元注解!
Java官方提供的注解,任何官方提供的非元注解的定义都使用到了元注解。

常用的元注解

* @Target
	作用:用来标识注解使用的位置,如果没有使用该注解标识,则自定义的注解可以使用在任意位置。
	可使用的值定义在ElementType枚举类中,常量值如下
        TYPE,类,接口
        FIELD, 成员变量
        METHOD, 成员方法
        PARAMETER, 方法参数
        CONSTRUCTOR, 构造方法
        LOCAL_VARIABLE, 局部变量
        ......
* @Retention
	作用:用来标识注解的生命周期(有效范围)
    可使用的值定义在RetentionPolicy枚举类中,常用值如下
        SOURCE:注解只作用在源码阶段,生成的字节码文件中不存在
        CLASS:注解作用在源码阶段,字节码文件阶段,运行阶段不存在,默认值
        RUNTIME:注解作用在源码阶段,字节码文件阶段,运行阶段

修改Book注解

@Target({ElementType.METHOD,ElementType.TYPE}) // 使用itheima注解只能作用于类(接口)上面或者方法上面!(用于其它位置就会报错!)
@Retention(RetentionPolicy.RUNTIME) // 使用注解,在代码运行的时候起到作用!
public @interface itheima {

    // 基本类型
    char a();

    // 字符串类型
    String b();

    // Class类型
    Class c();

    // 注解类型
    MyAnnotation d();

    // 枚举类型
    Sex e();

    // 数组
    int[] f();

}

四、注解解析

1.1 注解解析概念和原理

使用Java技术获得注解上数据的过程则称为注解解析。与注解解析相关的接口

* Annotation: 注解类,该类是所有注解的父类。
* AnnotatedElement:该接口定义了与注解解析相关的方法(Method/Field/Constructor等都实现了该接口)
    boolean  isAnnotationPresent(Class<Annotation> annotationClass) //判断当前对象是否使用了指定的注解,如果使用了则返回true,否则false
	T getAnnotation(Class<T> annotationClass)  // 根据注解类型获得对应注解对象
	Annotation[]   getAnnotations() //获得当前对象上使用的所有注解,返回注解数组,包含父类继承的
	Annotation[]   getDeclaredAnnotations() // 获得当前对象上使用的所有注解,返回注解数组,只包含本类的
* 获取注解数据的原理
	注解作用在哪个成员上就会得该成员对应的对象来获得注解
    	比如注解作用成员方法,则要获得该成员方法对应的Method对象
        比如注解作用在类上,则要该类的Class对象
        比如注解作用在成员变量上,则要获得该成员变量对应的Field对象。	 
	Field,Method,Constructor,Class等类都是实现了AnnotatedElement接口
1.2 注解解析演示

需求:

① 定义注解Book,要求如下:

② 定义BookStore类,在类和成员方法上使用Book注解

@Book(value = "JavaWeb核心指南", authors = {"张杰", "苏强"})
public class BookStore {

    // 成员方法
    @Book(value = "Linux删库跑路", authors = {"王金良", "何向日"}, price = 88)
    public void show() {

    }

}

③ 定义TestAnnotation测试类获取Book注解上的数据

/*
    定义TestAnnotation测试类获取Book注解上的数据
        比如注解作用成员方法,则要获得该成员方法对应的Method对象
        比如注解作用在类上,则要该类的Class对象
        比如注解作用在成员变量上,则要获得该成员变量对应的Field对象。
 */
public class TestAnnotaion {

    /*
        注解解析,获得BookStore类上面Book注解的里面属性对应的值
     */
    @Test
    public void testType(){
        // 获得Class对象
        Class<BookStore> bookStore = BookStore.class;

        // 判断类BookStore上面有没有使用Book注解!
        if(bookStore.isAnnotationPresent(Book.class)){
            // 获得类BookStore上面的注解对象!
            Book book = bookStore.getAnnotation(Book.class);
            // 获得注解属性的值
            String name = book.value();
            String[] authors = book.authors();
            double price = book.price(); // 获得默认值 100

            // 打印
            System.out.println("书名:" + name);
            System.out.println("作者:" + Arrays.toString(authors));
            System.out.println("价格:" + price);

        }

    }

    /*
        注解解析,获得BookStore类中show方法上面Book注解里面的属性对应的值
     */
    @Test
    public void testMethod() throws NoSuchMethodException {

        // 获得字节码对象
        Class<BookStore> bookStore = BookStore.class;
        // 获得指定的方法对象
        Method show = bookStore.getMethod("show");

        // 判断show方法上面有没有使用@Book注解
        if(show.isAnnotationPresent(Book.class)){
            // 通过Method对象获得show方法上面的注解对象!
            Book book = show.getAnnotation(Book.class);

            // 获得注解属性的值
            String name = book.value();
            String[] authors = book.authors();
            double price = book.price(); // 获得默认值 100

            // 打印
            System.out.println("书名:" + name);
            System.out.println("作者:" + Arrays.toString(authors));
            System.out.println("价格:" + price);

        }

    }

}

五、注解总结

一、注解的概念
1.注解是JDK1.5的新特性。
2. 注解相当一种标记,是类的组成部分,可以给类携带一些额外的信息。
3.标记(注解)可以加在包,类,字段(成员变量),方法,方法参数以及局部变量上。
4. 注解是给机器(jvm)看的,编译器或JVM可以根据注解来完成对应的功能;而注释是给人(程序员)看的!
二、自定义注解格式及属性格式

  • public @interface 注解名{
    // 里面定义属性即可!
    }
  • 属性定义的格式:
    格式1:数据类型 属性名();
    格式2:数据类型 属性名() default 默认值;
    三、元注解
  • @Target 作用:用来标识注解使用的位置,如果没有使用该注解标识,则自定义的注解可以使用在任意位置。

可使用的值定义在ElementType枚举类中,常量值如下
TYPE,类,接口
FIELD, 成员变量
METHOD, 成员方法
PARAMETER, 方法参数
CONSTRUCTOR, 构造方法
LOCAL_VARIABLE, 局部变量

  • @Retention 作用:用来标识注解的生命周期(有效范围)

可使用的值定义在RetentionPolicy枚举类中,常用值如下
SOURCE:注解只作用在源码阶段,生成的字节码文件中不存在
CLASS:注解作用在源码阶段,字节码文件阶段,运行阶段不存在,默认值
RUNTIME:注解作用在源码阶段,字节码文件阶段,运行阶段

四、注解解析

* Annotation: 注解类,该类是所有注解的父类。
* AnnotatedElement:该接口定义了与注解解析相关的方法(Method/Field/Constructor等都实现了该接口)
    boolean  isAnnotationPresent(Class<Annotation> annotationClass) //判断当前对象是否使用了指定的注解,如果使用了则返回true,否则false
	T getAnnotation(Class<T> annotationClass)  // 根据注解类型获得对应注解对象
	Annotation[]   getAnnotations() //获得当前对象上使用的所有注解,返回注解数组,包含父类继承的
	Annotation[]   getDeclaredAnnotations() // 获得当前对象上使用的所有注解,返回注解数组,只包含本类的
* 获取注解数据的原理
	注解作用在哪个成员上就会得该成员对应的对象来获得注解
    	比如注解作用成员方法,则要获得该成员方法对应的Method对象
        比如注解作用在类上,则要该类的Class对象
        比如注解作用在成员变量上,则要获得该成员变量对应的Field对象。	 
	Field,Method,Constructor,Class等类都是实现了AnnotatedElement接口
  • 2
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值