Java中注解(Annotations)的使用

Java中注解(Annotations)的使用

肖扬

Java中的注解(Annotaitons)

一、什么是注解?

Java1.5版本后,引入Java注解,Java开发者可以自定义自己的注解满足业务的需求
Java引入注解后,也提供了注解的获取方式,在Class类中,可以通过getAnnotation()获取

二、注解可以做什么?

注解可以做很多事情
比如:

  1. @Override类似的注解,生命周期在源码级别,可以提供编译器,检测不规范java代码
  2. springboot就是基于注解驱动的,极大的便利了开发者
  3. 项目中依赖的第三方jar中,比如 @DateFormat提供了实体响应时自动转换时间字段等
  4. Java开发者亦可以自定义自己的注解,满足个性的需求,比如:数据词典转换,bean加载过滤、上下文扫描等

三、注解的使用

1、什么是元注解

常见的四种元注解

  1. @Documneted
  2. @Retention
  3. @Target
  4. @Inherited
@Documented

注解是否将包含在JavaDoc中

@Documented–一个简单的Annotations标记注解,表示是否将注解信息添加在java文档中。

@Retention

表示什么时候使用该注解,或者说定义注解的存在的时间点(生命周期)

@Retention 定义该注解的生命周期。

1、RetentionPolicy.SOURCE

在编译阶段丢弃。这些注解在编译结束之后就不再有任何意义,所以它们不会写入字节码。
比如:@Override, @SuppressWarnings都属于这类注解。

2、RetentionPolicy.CLASS

在类加载的时候丢弃。在字节码文件的处理中有用。注解默认使用这种方式。不保证JVM能够获取

3、RetentionPolicy.RUNTIME

始终不会丢弃,运行期也保留该注解,因此可以使用反射机制读取该注解的信息。在JVM中也能获取的到。
我们自定义的注解通常使用这种方式。

@Target

表示注解用于什么地方,也可以理解为标明了此注解可以使用的位置

@Target 表示该注解用于什么地方。如果不明确指出,该注解可以放在任何地方。(如果一个注解未使用@Target元注解,那么表示此注解可以用在任何可以标记注解的位置,但是一般为了书写规范,最好指明@Target,更方便理解注解的使用场景)。

以下是一些可用的参数。
需要说明的是:
属性的注解是兼容的,如果你想给7个属性都添加注解,仅仅排除一个属性,那么你需要在定义target包含所有的属性。

ElementType.TYPE:用于描述类、接口、注解或枚举上声明
ElementType.FIELD:用于描述实例变量
ElementType.METHOD:表示可用用在方法上
ElementType.PARAMETER : 表示可以用在参数上
ElementType.CONSTRUCTOR : 表示可以用在构造方法上
ElementType.LOCAL_VARIABLE :表示可以用在本地变量山
ElementType.ANNOTATION_TYPE: 表示可以用在注解上
ElementType.PACKAGE:用于记录java文件的package信息

@Inherited

表示允许子类继承该注解

@Inherited – 定义该注释和子类的关系
如果添加了此注解,表示标记此注解的类的子类都可以获取到父类的注解

2、如何定义注解

基于上述的元注解,我们可以自定义自己的注解。

除去四大基础的元注解外,其他的注解都是基于元注解做的封装,可以根据自己的需求自定义相关注解,并给与注解相关实现,以赋予某种特定的意义

下面我们来简单的创建一个自己的时间格式转换注解
功能如下:

  1. 注解标记在属性上
  2. 可以指定时间转换的格式

步骤一:自定义注解

package com.starry.sky.java8;

import java.lang.annotation.*;

/**
 * author:xuxiaoyang
 * date:2021/12/19.
 * time:13:15.
 * Description:
 */
@Documented //是否将注解信息添加到java文档中
@Retention(RetentionPolicy.RUNTIME)//定义该注解的生命周期
@Target(ElementType.FIELD)//指定注解使用的位置,此处定义只能使用在属性上
public @interface DateFormat {

    String format() default "";//默认格式为空,则不转换
}

步骤二:定义实体类,并标注 自定义注解

package com.starry.sky.java8.entity;

import com.starry.sky.java8.DateFormat;

/**
 * author:xuxiaoyang
 * date:2021/12/19.
 * time:13:17.
 * Description:
 */
public class User {

    /**
     * 时间
     * 传入时间格式为 yyyyMMdd
     */
    @DateFormat(format = "yyyy-MM-dd") //将字段date的值从yyyyMMdd转换为yyyy-MM-dd
    private String date;

    public String getDate() {
        return date;
    }

    public void setDate(String date) {
        this.date = date;
    }

    @Override
    public String toString() {
        return "User{" +
                "date='" + date + '\'' +
                '}';
    }
}

步骤三:执行注解

这里只是用main方法测试注解的使用

package com.starry.sky.java8;

import com.starry.sky.java8.entity.User;

import java.lang.reflect.Field;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;

/**
 * 测试java注解
 * @author xiaoyang
 * @version 1.0.0
 * @createTime 2021/11/27 22:13
 * @description
 */
public class Java8Demo {


    public static void main(String[] args) {
        User user = new User();
        user.setDate("20211212");
        System.out.println("源实体类:"+user.toString());
        //获取标记注解的字段
        //1 获取所有的字段
        Field[] fields = user.getClass().getDeclaredFields();
        //2 遍历字段获取字段上是否标记DateFormat注解
        for(Field field : fields) {
            DateFormat format = field.getAnnotation(DateFormat.class);
            if(format != null) {
                String formatWay = format.format();
                if(!"".equals(formatWay)) {
                    //转换时间类型
                    SimpleDateFormat fmtSources = new SimpleDateFormat("yyyyMMdd");
                    SimpleDateFormat fmtTarget = new SimpleDateFormat(formatWay);
                    try {
                        //设置字段可访问,否则无法访问private修饰的字段
                        field.setAccessible(true);
                        String fieldValue = (String) field.get(user);
                        Date date = fmtSources.parse(fieldValue);
                        String result = fmtTarget.format(date);
                        field.set(user,result);
                    } catch (ParseException | IllegalAccessException e) {
                        e.printStackTrace();
                    }
                }
            }
        }
        System.out.println("转换后实体类:"+user.toString());
    }
}

执行main方法后输入:



Connected to the target VM, address: '127.0.0.1:3759', transport: 'socket'
源实体类:User{date='20211212'}
转换后实体类:User{date='2021-12-12'}
Disconnected from the target VM, address: '127.0.0.1:3759', transport: 'socket'

Process finished with exit code 0


上面的打印,着重看第二行第三行
第二行为实体类未转换前的输出
第三行为实体类转换后的输出

注解方式大概如上面实例的这样,
但是注解的核心在于方法或者类的头上使用注解在程序运行时通过反射获取注解信息,然后根据注解的信息进行特殊逻辑的处理等

四、常用的注解

Java开发者最常使用的框架莫过于Spring了,下面是spring中常用注解描述:
详情请点击查看:
Spring中常用的注解

多少不凡、只因不甘

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值