深入理解java注解@机制

深入理解java注解@机制

大家好,我是架构君,一个会写代码吟诗的架构师。今天说一说深入理解java注解@机制,希望能够帮助大家进步!!!

1.   注解

什么注解?

 

注解:annotation(标识,标签),从Java5开始支持注解

 

注解能干什么?

 

注解是贴在java程序元素上面

 

程序元素 : 类,方法,字段,方法参数,接口,构造函数,枚举

 

注解贴在程序上面有什么用?

 

在反射的时候,动态可以获取字节码,方法,字段等等程序元素,获取了这些程序元素,那么就能获取程序元素上贴的注解。这些注解会参与程序运行提供比较的相关信息和数据

 

枚举是一个特殊类

注解是一个特殊的接口,所有的注解都继承自java.lang.annotation这个接口。

 深入理解java注解@机制

 

 

 

完整的注解(从编写到最终运行)需要三方面的参与。

                  1.需要定义一个注解。

                  2.需要一个被贴的程序元素(类,方法,字段,构造器等)

                  3.第三方程序的支持(赋予我注解的特殊功能)

 深入理解java注解@机制

 

 

 

1.1. JDK中内置的注解

1.@Override   限定覆写父类方法

2.@Deprecated  标记已过时的成员,被标记的方法不推荐使用.

 

问题1:有的注解可以贴在类上,方法上,字段上,有的却只能贴在类上

问题2:有的注解可以有一个或者多个参数,有的却不行。

 

 

1.2. JDK中的元注解

 

注解: 贴在程序元素上面的标签

元注解 : 注解的注解(贴在注解上面的注解)

元注解 主要用于限定当前的注解能够贴在哪儿?能够保留在哪个阶段(程序执行三个阶段

源代码阶段,字节码阶段,JVM中)

 

@Retention:  表示注解可以保存在哪一个时期.

              保存的时期的值,封装在RetentionPolicy枚举类中

枚举常量摘要

CLASS

注解保留到字节码阶段,运行时候失效了

RUNTIME

注解保留到运行阶段,运行时候使用反射获取做相应的程序处理-一般开发者自定注解都保留运行阶段

SOURCE

注解在源代码阶段有效,编译字节码就失效了

 

 

 

@Target:      表示注解可以贴在哪些位置(类,方法上,构造器上等等).

               位置的常量封装在ElementType枚举类中:

ElementType.ANNOTATION_TYPE只能修饰Annotation

ElementType.CONSTRUCTOR只能修饰构造方法

ElementType.FIELD只能修饰字段(属性),包括枚举常量

ElementType.LOCAL_VARIABLE只能修饰局部变量

ElementType.METHOD只能修饰方法

ElementType.PACKAGE只能修饰包(极少使用)

ElementType.PARAMETER只能修饰参数

ElementType.TYPE只能修饰类,接口,枚举

 

 

枚举常量摘要

ANNOTATION_TYPE

注释类型声明

CONSTRUCTOR

构造方法声明

FIELD

字段声明(包括枚举常量)

LOCAL_VARIABLE

局部变量声明

METHOD

方法声明

PACKAGE

包声明

PARAMETER

参数声明

TYPE

类、接口(包括注释类型)或枚举声明

 

 

 

 

1.3. 自定义注解

1. 定义一个注解

 

语法 : 注解关键字  @Interface

 

2. 被贴的程序元素

3. 第三方程序参与赋予注解功能(反射程序)

 

程序代码

package cn.zj.annotation;


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

/**
 *
设置注解的元注解
 
* 1Target
 *  
注解可以贴在那些程序元素上面
 
* 2, Retention
 * 
注解可以保留到那个阶段,一般自定义保留到RUNTIME运行时
 
*
 */
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface Table {
    /**
     *
注解属性
    
语法
    
数据类型  属性名称();
     * 
如果属性名称是 value ,在使用注解的时候,可以省略 value
     */

    //String value();
   
String name();

}

 

package cn.zj.annotation;


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

@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Column {

    String value();
}

 

package cn.zj.pojo;


import cn.zj.annotation.Column;

import cn.zj.annotation.Table;

/**
 * @Table
注解的作用就是为了解决在反射时候,实体类和 表明不匹配
 
实体类 :User --> user 理论上对应数据表  user
 * 
实际上数据库表名 :t_user
 * 
这样如果默认不匹配 反射时候对不上,反射封装存储数据就失败
 
*/

@Table(name="t_user")
public class User {
    private Integer id;

    @Column("username")
    private String name;
    private String password;
    private String email;
    private String phone;



    public Integer getId() {
        return id;
    }

    public String getName() {
        return name;
    }

    public String getPassword() {
        return password;
    }

    public String getEmail() {
        return email;
    }

    public String getPhone() {
        return phone;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public void setName(String name) {
        this.name = name;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    public void setEmail(String email) {
        this.email = email;
    }

    public void setPhone(String phone) {
        this.phone = phone;
    }

    @Override
    public String toString() {
        return "User{" +
                "id=" + id +
                ", name='" + name + '\'' +
                ", password='" + password + '\'' +
                ", email='" + email + '\'' +
                ", phone='" + phone + '\'' +
                '}';
    }
}

 

测试代码

package cn.zj.test;

import cn.zj.annotation.Column;
import cn.zj.annotation.Table;
import cn.zj.pojo.User;

import java.lang.reflect.Field;

public class AnnotationTest {

    //使用反射获取字节码,并获取对应元素的注解
   
public static void main(String[] args) {

        //1.获取User类的字节码实例
      
Class<User> clz =  User.class;

       //2.判断类上面是否有 @Table注解

       
boolean flag = clz.isAnnotationPresent(Table.class);
        if(flag){
           
            //1.获取@Table注解
           
Table table = clz.getAnnotation(Table.class);

            System.out.println(table);

            //2.获取具体的属性值
           
String tableName = table.name();

            System.out.println(tableName);

        }


        //2.获取所有字段

       
Field[] fields = clz.getDeclaredFields();

        for (Field field : fields) {
            //1.判断字段上是否有注解

           
if(field.isAnnotationPresent(Column.class)){

               //2.获取字段上的注解
               
Column column = field.getAnnotation(Column.class);
                System.out.println(column);

            }
        }


    }

}

 

转载于:https://www.cnblogs.com/shenzhenhuicnblogs/p/11099663.html

本文来源weixin_30595035,由架构君转载发布,观点不代表Java架构师必看的立场,转载请标明来源出处:https://javajgs.com/archives/29734

发表评论