Java基础之注解精讲

1. Java猿的命根子!

自Java EE框架步入Spring Boot时代之后,注解简直是Java程序员的命根子啊,面向注解编程成了日常操作!

换句话的意思就是说:如果没有注解,我们啥也干不了哇(滑稽)

这岂不是很危险!

所以本文来唠一唠关于注解的相关操作,并自己动手来写一个注解感受一下原理。原理性的东西掌握了,心里自然就不慌了。

2. 注解的基本原理

首先必须要说的是,注解它也不是什么高深的玩意儿,没必要畏惧它!

意如其名,其本来的意思就是用来做标注用:可以在类、字段变量、方法、接口等位置进行一个特殊的标记,为后续做一些诸如:代码生成、数据校验、资源整合等工作做铺垫。

对嘛,就做标记用的嘛!

注解一旦对代码标注完成,后续我们就可以结合Java强大的反射机制,在运行时动态地获取到注解的标注信息,从而可以执行很多其他逻辑,完成我们想要的自动化工作。

所以,反射必须要学好!

3. 来!动手造一个注解

Spring自身提供了非常多好用的注解可以用来方便地帮我们做数据校验的工作。

比如,在没有注解加持时,我们想要校验Student类:

public class Student {
	private Long id; // 学号
	private String name;// 姓名
	private String mobile;// 手机号码(11位)
}

我们只能通过手写if判断来进行校验:

@PostMapping("/add")
public String addStudent( @RequestBody Student student ) {
    if( student == null )
        return "传入的Student对象为null,请传值";
    if( student.getName()==null || "".equals(student.getName()) )
        return "传入的学生姓名为空,请传值";
    if( student.getScore()==null )
        return "传入的学生成绩为null,请传值";
    if( (student.getScore()<0) || (student.getScore()>100) )
        return "传入的学生成绩有误,分数应该在0~100之间";
    if( student.getMobile()==null || "".equals(student.getMobile()) )
        return "传入的学生电话号码为空,请传值";
    if( student.getMobile().length()!=11 )
        return "传入的学生电话号码长度有误,应为11位";
        
    studentService.addStudent( student );// 将student对象存入MySQL数据库
    return "SUCCESS";
}

这样非常繁琐!

但是借助于Spring提供的注解,数据校验工作可以变得非常优雅,就像这样:

public class Student {
	@NotNull(message = "传入的姓名为null,请传值")
	@NotEmpty(message = "传入的姓名为空字符串,请传值")
    private String name;// 姓名
    
	@NotNull(message = "传入的分数为null,请传值")
	@Min(value = 0,message = "传入的学生成绩有误,分数应该在0~100之间")
    @Max(value = 100,message = "传入的学生成绩有误,分数应该在0~100之间")
	private Integer score;// 分数
	
	@NotNull(message = "传入的电话为null,请传值")
	@NotEmpty(message = "传入的电话为空字符串,请传值")    
	@Length(min = 11, max = 11, message = "传入的电话号码长度有误,必须为11位")
    private String mobile; // 电话号码
}

于是很多人就表示疑问,这些注解到底如何实现功能的呢?

今天本文则以上文的@Length注解为例,自己动手实现一遍,这个学会了,其他注解实现原理也是类似。

总共分三大步实现。

第一步:首先定义注解:@Length

@Target({ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
public @interface Length {
    int min(); // 允许字符串长度的最小值
    int max(); // 允许字符串长度的最大值
    String errorMsg(); // 自定义的错误提示信息
}

下面做几点说明:

  • 1、注解的定义有点像定义接口interface,但唯一不同的是前面需要加一个@符号

  • 2、注解的成员变量只能使用基本类型、String或者enum枚举,比如int可以,但 Integer这种包装类型就不行,需注意

  • 3、像上面@Target@Retention这种加在注解定义上面的注解,我们称为 “元注解”,元注解就是专门用于给注解添加注解的注解,哈哈,很拗口,简单理解,元注解就是天生就有的注解,可直接用于注解的定义上

  • 4、@Target(xxx)用来说明该自定义注解可以用在什么位置,比如:

    • ElementType.FIELD:说明自定义的注解可以用于类的变量
    • ElementType.METHOD:说明自定义的注解可以用于类的方法
    • ElementType.TYPE:说明自定义的注解可以用于类本身、接口或 enum类型
    • 等等… 还有很多,如果记不住,建议现用现查
  • 5、@Retention(xxx)用来说明你自定义注解的生命周期,比如:

    • @Retention(RetentionPolicy.RUNTIME):表示注解可以一直保留到运行时,因此可以通过反射获取注解信息
    • @Retention(RetentionPolicy.CLASS):表示注解被编译器编译进class文件,但运行时会忽略
    • @Retention(RetentionPolicy.SOURCE):表示注解仅在源文件中有效,编译时就会被忽略
    • 所以声明周期从长到短分别为:RUNTIME > CLASS > SOURCE ,一般来说,如果需要在运行时去动态获取注解的信息,还是得用RUNTIME,就像本文所用。

第二步:获取注解并对其进行验证

在运行时想获取注解所代包含的信息,该怎么办?那当然得用 Java的反射相关知识!

下面写了一个验证函数validate(),代码中会逐行用注释去解释想要达到的目的,认真看一下每一行的注释:

public static String validate( Object object ) throws IllegalAccessException{   
	// 首先通过反射获取object对象的类有哪些字段   
	// 对本文来说就可以获取到Student类的id、name、mobile三个字段
    Field[] fields = object.getClass().getDeclaredFields();
    
	// for循环逐个字段校验,看哪个字段上标了注解
    for( Field field : fields ) {
		// if判断:检查该字段上有没有标注了@Length注解
        if( field.isAnnotationPresent(Length.class) ) {     
			// 通过反射获取到该字段上标注的@Length注解的详细信息
            Length length = field.getAnnotation( Length.class );
            field.setAccessible( true );
			// 让我们在反射时能访问到私有变量
			// 用过反射获取字段的实际值
            int value =( (String)field.get(object) ).length();
            // 将字段的实际值和注解上做标示的值进行比对
            if( value<length.min() || value>length.max() ) {
                return length.errorMsg();
            }
        }
    }
    return null;
}

可见,学好Java的反射知识是多么的重要!

第三步:使用注解

这一步比较轻松,使用注解的过程往往都是很愉悦的

public class Student {
    private Long id;// 学号
    private String name;// 姓名
    @Length(min = 11, max = 11, errorMsg = "电话号码的长度必须为11位")
    private String mobile; // 手机号码(11位)
}
  • 2
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Java基础思维导图是一个用Xmind软件制作的图形化思维导图,用于梳理和总结Java编程语言的基础知识和概念。 Java基础思维导图包含了Java语言的核心内容,涵盖了面向对象的基本概念、Java的语法规则、数据类型、流程控制、数组、字符串、异常处理、输入输出等方面的知识点。通过这个思维导图,可以清晰地了解Java基础知识结构,并且将各个知识点之间的关系和联系展示出来。 在Java基础思维导图中,我们会看到Java语言的特点和优势,例如跨平台性、面向对象、安全性等。然后会详细介绍Java程序的基本结构,包括类、方法、变量等的概念和用法,以及Java的命名规范和注释的使用。 接下来,思维导图会讲解Java的数据类型,包括基本数据类型和引用数据类型的定义和使用方法。然后会介绍Java中的运算符、流程控制和循环结构,以及条件语句和循环语句的使用。 在思维导图的其他分支中,我们还会了解Java中的数组和字符串的使用方法,以及常用的库函数。同时也会学习Java的异常处理机制,包括try-catch语句的使用和异常类的继承关系。 最后,思维导图还会涵盖Java的输入输出和文件操作,包括标准输入输出、文件读写的方法和常用类的使用。 通过Java基础思维导图,我们能够清晰地了解Java编程语言的基础知识和概念,有助于我们系统学习和练习Java编程,提高我们的编程能力。同时,这个导图也可以作为日后查阅的工具,方便我们回顾和复习Java基础知识。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值