Javase注解学习笔记

  • 注解
  1. 概述: 注解(Annotation),也叫元数据。一种代码级别的说明。它是JDK5及以后版本引入的一个特性,与类、接口、枚举是在同一个层次。它可以声明在包、类、字段、方法、局部变量、方法参数等的前面,用来对这些元素进行说明,注释。

  1. 注解的作用:
  1. 编写文档:通过代码里标识的注解生成文档【例如,生成文档javadoc文档】

   @author  @version  @param  @return

  1. 代码分析:通过代码里标识的注解对代码进行分析【例如,注解的反射】

   注解的底层实现原理 : 就是通过反射机制完成的

  1. 编译检查:通过代码里标识的注解让编译器能够实现基本的编译检查【例如,Override,FunctionalInterface】

  1. 常见注解:
  1.  @author:用来标识作者名
  2.  @version:用于标识对象的版本号,适用范围:文件、类、方法。
  3.  @Override:

         用来修饰方法声明,告诉编译器该方法是重写父类中的方法,如果父类不存在该方法,则编译失败。

注解和注释是完全不同的

  1. 注解会影响代码的运行, 注释不会影响代码的运行;
  2. 注释是给程序员看的, 注解不是给人看的, 是对于程序的编译和运行起到一定作用的

  • 自定义注解
  1. 定义格式:

    元注解

    public @interface 注解名称{

        属性列表;

}

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

   相当于:

       public interface MyAnnotation extends java.lang.annotation.Annotation {}

   举例 :

   public @interface Person{}

  1. 注解不需要写任何的逻辑, 因为注解式标注

  • 元注解
  1. 元注解:用来描述注解的注解
  2. 分类:

    @Target描述注解能够作用的位置(指定使用的地方)

           value值:是一个ElementType[]

                   常用取值:

                            1、ElementType.TYPE : 针对类和接口使用

                            2、ElementType.METHOD : 针对方法使用

                            3、ElementType.FILED : 针对变量使用

    @Retention注解被保留的阶段

           value值:是一个RetentionPolicy枚举RetentionPolicy(翻译: 保留策略)

                   取值:

  1. RetentionPolicy.SOURCE---【在源代码中不会到字节码文件中】

     编译器运行时, 进行识别(编译时期识别), 例如@Override

                            2、RetentionPolicy.CLASS---【编译到字节码文件中但是运行时jvm不会读取】注解信息保留到类对应的class文件中

                            3、RetentionPolicy.RUNTIME--【编译到字节码文件中运行时jvm会读取,运行时使用】运行时期生效的注解一般都是筛选的作用 例如: @FunctionalInterface

          例如: 程序运行时起作用的,@WebServlet, 代码运行时,检测哪些类型是Servlet

    @Documented :描述注解是否被抽取到API文档中

    @Inherited:注解是否被子类继承

代码

package com.ujiuye.ano;

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 InitMethod {
}

  • 注解通过反射机制解析运行

代码

package com.ujiuye.ano;

public class UseInitMethod {
    @InitMethod
    public void init(){
        System.out.println("类UseInitMethod一旦进入内存,init方法马上运行");
    }

    @InitMethod
    public void test(){
        System.out.println("类UseInitMethod一旦进入内存,test方法马上运行");
    }

    public void fun(){
        System.out.println("只有创建对象调用才运行");
    }
}

package com.ujiuye.ano;

  

import java.lang.reflect.InvocationTargetException;

import java.lang.reflect.Method;

  

// 测试带有自定义的InitMethod注解的方法,通过反射机制运行

public class TestInitMethod {

    public static void main(String[] args) throws IllegalAccessException, InstantiationException, InvocationTargetException {

        // 1. 获取到带有注解的类型在内存中对应的Class字节码文件对象

        Class c = UseInitMethod.class;

        // 2. 通过Class类型对象, 获取到所有方法

        Method[] m = c.getDeclaredMethods();

        // 3. 遍历m数组,获取到每一个方法

        for(Method me : m){

            // 注意 : Method类型的父类Accessiable中继承给Method的方法

            // isAnnotationPresent(Class 注解): 验证方法上是否带有参数的注解

            // 如果带有返回true, 如果没有返回false

            boolean boo = me.isAnnotationPresent(InitMethod.class);

            if(boo){// 方法上带有InitMethod注解,马上运行

               me.invoke(c.newInstance());

            }

        }

    }

}

@Override注解模拟解析

package com.ujiuye.ano;

  

public class Zi extends FU{

    /*

         剖析Override注解解析方式:

           1) 当类进入到编译阶段,马上检测当前类型中,有哪些方法使用了Override注解

           2) 将所有的带有Override方法获取到

           3) 遍历获取每一个方法,到父类类型中,寻找,是否有与重写的方法一样的方法声明(包括修饰符的检查)

              a : 父类有, Override成立,不报错

              b : 父类没有, 或者权限不对,报错

     */

    @Override

    public void show(){

        System.out.println("我是子类重写");

    }

  

    /*@Override

    public void fun(){

        System.out.println("我是子类重写");

    }*/

}

  • 注解的属性
  1. 属性的作用: 可以让用户在使用注解时传递参数,让注解的功能更加强大。
  2. 属性的格式:

    public @interface 注解名称{

        属性列表;

}

       - 格式1:数据类型 属性名();

- 格式2:数据类型 属性名() default 默认值;

  1. 属性适用的数据类型
  1. 八种基本数据类型(int,float,boolean,byte,double,char,long,short)
  2. String类型,Class类型,枚举类型,注解类型
  3. 以上所有类型的一维数组
  1. 注意事项:
  1. 如果属性有默认值,则使用注解的时候,这个属性可以不用赋值。

2) 如果属性没有默认值,那么在使用注解时一定要给属性赋值。

代码

package com.ujiuye.ano;

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 Person {
    // Person注解中添加属性
    String name();
    int age() default 18;
    String sex() default "
";
}

  • 注解的解析

注解只是标注, 注解在加载时, 通过反射机制将注解需要完成的功能进行实现

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

    1. 获取注解定义的位置的对象  (Class,Method,Field)

    2. 获取指定的注解 Class类中方法: getAnnotation(Class)

         3. 调用注解中的抽象方法获取配置的属性值

使用格式:

         @注解名(属性名=属性值,属性名=属性值,属性名=属性值...)

代码

package com.ujiuye.ano;

@Person(name="金莲",age=16)
public class TestPerson {
    public static void main(String[] args) {
        // 1. 获取到使用了注解类型对应的Class字节码文件对象
        Class<TestPerson> c = TestPerson.class;
        // 2. 获取到类TestPerson上对应的注解
        // Class 类型中: 方法功能getAnnotation(Class 注解),表示直接将类上注解获取到
        Person per = c.getAnnotation(Person.class);
        // 3. 获取Person注解中属性值
        String name = per.name();
        int age = per.age();
        String sex = per.sex();
        System.out.println(name + "--" + age + "--" + sex);// 金莲--16--男
    }
}

  • 3
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值