Java 注解学习笔记

注解说明

Java注解又称Java标注,是Java语言5.0版本开始支持加入源代码的特殊语法元数据。为我们在代码中添加信息提供了一种形式化的方法,使我们可以在稍后某个时刻非常方便的使用这些数据。Java语言中的类、方法、变量、参数和包等都可以被标注。和Javadoc不同,Java标注可以通过反射获取注解内容。在编译器生成类文件时,注解可以被嵌入到字节码中。Java虚拟机可以保留注解内容,在运行时可以获取到注解内容。

内置注解

Java定义了一套注解,共有7个,3个在java.lang中,剩下4个在java.lang.annotation中。

1.作用在代码的注解是:

  • @Override - 检查该方法是否是重写方法。如果发现其父类,或者是引用的接口中并没有该方法时,会报编译错误。
  • @Deprecated - 标记过时方法。如果使用该方法,会报编译警告。
  • @SuppressWarnings - 指示编译器去忽略注解中声明的警告。

2.作用在其他注解的注解(或者说元注解)是:

  • @Retention - 标识这个注解怎么保存,是只在代码中,还是编入class文件中,或者是在运行时可以通过反射访问。
  • @Documented - 标记这些注解是否包含在用户文档中。
  • @Target - 标记这个注解应该是哪种Java成员。
  • @Inherited - 标记这个注解是继承于哪个注解类(默认注解并没有继承于任何子类)

3.从Java 7开始,额外添加了3个注解:

  • @SafeVarargs - Java 7开始支持,忽略任何使用参数为泛型变量的方法或构造函数调用产生的警告。
  • @FunctionalInterface - Java 8开始支持,标识一个匿名函数或函数式接口。
  • @Repeatable - Java 8开始支持,标识某注解可以在同一个声明上使用多次。

元注解

元注解就是上面说到的作用在其他注解上的注解。

1.@Retention:表明该注解的生命周期

生命周期类型 描述
RetentionPolicy.SOURCE 标记的注释仅保留在源级别中,并由编译器忽略。
RetentionPolicy.CLASS 标记的注释在编译时由编译器保留,但Java虚拟机(JVM)会忽略。
RetentionPolicy.RUNTIME 标记的注释由JVM保留,因此运行时环境可以使用它。

2.@Documented:表明该注解标记的元素可以被Javadoc或类似的工具文档化

3.@Target: 表明该注解可以应用的java元素类型

Target类型 描述
ElementType.TYPE 可以应用于类的任何元素。
ElementType.FIELD 可以应用于字段或属性。
ElementType.METHOD 可以应用于方法级注释。
ElementType.PARAMETER 可以应用于方法的参数。
ElementType.CONSTRUCTOR 可以应用于构造函数。
ElementType.LOCAL_VARIABLE 可以应用于局部变量。
ElementType.ANNOTATION_TYPE 可以应用于注释类型。
ElementType.PACKAGE 可以应用于包声明。
ElementType.TYPE_PARAMETER 1.8版本新增,应用于类型变量
ElementType.TYPE_USE 1.8版本新增,应用于任何使用类型的语句中(例如声明语句、泛型和强制转换语句中的类型)

4.@Inherited:表明使用了@Inherited注解的注解,所标记的类的子类也会拥有这个注解

5.@Repeatable:Java SE 8中引入的,@Repeatable注释表明标记的注释可以多次应用于相同的声明或类型使用(即可以重复在同一个类、方法、属性等上使用)。

自定义注解

其实说了这么多,都是一些总结性的知识点,我敢说到现在,大家还是对注解是云里雾里的。想要更好的认识注解,只有我们自己定义一个注解,来实现一个我们的注解,通过实现一个我们自己的注解来熟悉注解的工作流程。

Java中自定义注解和创建一个接口相似,声明一个注解要用到以下东西:

  • 修饰符:访问修饰符必须为public,不写默认为pubic;
  • 关键字:关键字为@interface;
  • 注解名称:注解名称为自定义注解的名称,使用时还会用到;
  • 注解类型元素:注解类型元素是注解中内容,可以理解成自定义接口的实现部分。

同时需要注意以下事项:

  • 注解方法不能有参数;
  • 注解方法的返回类型局限于原始类型,字符串,枚举,注解,或以上类型构成的数组;
  • 注解方法可以包含默认值;
  • 注解可以包含与其绑定的元注解,元注解为注解提供信息。

规则知道了,下面我来编码实现一个自定义的注解。比如我们在实现一个自定义的ORM框架的时候,都会通过注解来实现数据表名与JAVA类的映射,表字段与JAVA类字段的映射关系,下面就来简单实现这个功能。

定义Table注解:

package com.jellythink.annotation;

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

@Target(value={ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface Table {
   String value();
}

定义字段注解:

package com.jellythink.annotation;

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

@Target(value={ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
public @interface FieldMapping {
   String name();
   String type();
   int length();
}

应用注解:

package com.jellythink;

import com.jellythink.annotation.FieldMapping;
import com.jellythink.annotation.Table;

@Table("tb_student")
public class Student {
   @FieldMapping(name = "id", type = "int", length = 10)
   private int id;

   @FieldMapping(name = "name", type = "varchar", length = 6)
   private String stuName;

   @FieldMapping(name = "age", type="int", length = 4)
   private String stuAge;

   // 省略getter and setter
}

读取注解信息:

package com.jellythink;

import com.jellythink.annotation.Table;
import com.jellythink.annotation.FieldMapping;

import java.lang.reflect.Field;

public class Main {

   public static void main(String[] args) {
       try {
           Class clazz = Class.forName("com.jellythink.Student");

           // 查询类上的注解
           Table tbStudent = (Table)clazz.getAnnotation(Table.class);
           System.out.println(tbStudent.value());

           // 查询属性上的注解
           Field stuId = clazz.getDeclaredField("id");
           FieldMapping fieldStuId = stuId.getAnnotation(FieldMapping.class);
           System.out.println(fieldStuId.name() + "--" + fieldStuId.type() + "--" + fieldStuId.length());

           Field stuName = clazz.getDeclaredField("stuName");
           FieldMapping fieldStuName =
                   stuName.getAnnotation(FieldMapping.class);
           System.out.println(fieldStuName.name() + "--" + fieldStuName.type() + "--" + fieldStuName.length());

           Field stuAge = clazz.getDeclaredField("stuAge");
           FieldMapping fieldStuAge =
                   stuName.getAnnotation(FieldMapping.class);
           System.out.println(fieldStuAge.name() + "--" + fieldStuAge.type() + "--" + fieldStuAge.length());

           // 通过上面查询到的数据拼接成SQL语句
           String name = "果冻";
           String sql =
                   "select * from " + tbStudent.value() + " where " + fieldStuName.name() + " = '" + name + "'";
           System.out.println("SQL=" + sql);
      } catch (Exception e) {
           // Handle the exception
      }
  }
}

通过上面的代码,有木有感受到自定义注解还是非常简单的;同时有没有感觉到注解这个功能是非常强大的。

总结

总的来说,注解这个功能很强大,但是使用起来确是非常简单的,这就是牛叉东西的特点,好用又让人不感觉到复杂。以后再遇到注解东西,内心就不再犯怵,不再迷茫了。

以上就是Java 注解学习笔记的详细内容,更多关于Java 注解的资料请关注我们其它相关文章!

(0)

相关推荐

  • Java注解之Retention、Documented、Inherited介绍

    Retention注解 Retention(保留)注解说明,这种类型的注解会被保留到那个阶段. 有三个值: 1.RetentionPolicy.SOURCE -- 这种类型的Annotations只在源代码级别保留,编译时就会被忽略 2.RetentionPolicy.CLASS -- 这种类型的Annotations编译时被保留,在class文件中存在,但JVM将会忽略 3.RetentionPolicy.RUNTIME -- 这种类型的Annotations将被JVM保留,所以他们能在运行时

  • java注解之运行时修改字段的注解值操作

    今天遇到需求:导入Excel时候列头会发生变化,客户是大爷要求你改代码, 导入Excel是用easypoi做的,识别表头是用注解@Excel(name = "xxx")通过这个name来匹配 那你表头要动,我这个注解是硬编码 所以就有动态设置这个表头 public class JavaVo{ @Excel(name = "xxx") private String userName; //省略getset方法 } ExcelImportUtil.importExcel

  • javax.validation自定义日期范围校验注解操作

    实际项目中经常需要对传入的日期时间进行判断,如是否为一年内,几个月之内,几天前,几天之内等等的需求. 如要求前端传入的日期是要为当前日期一年内的某个日期,基于jdk8的LocalDateTime or LocalDate等常用的做法如下: // 前端传字符串如'2020-07-13 09:09:09' springmvc接收并转换为LocalDateTime类型 @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd

  • 详解Java的Spring框架中的注解的用法

    1. 使用Spring注解来注入属性 1.1. 使用注解以前我们是怎样注入属性的 类的实现: class UserManagerImpl implements UserManager { private UserDao userDao; public void setUserDao(UserDao userDao) { this.userDao = userDao; } ... } 配置文件: <bean id="userManagerImpl" class="com.

  • java SpringBoot自定义注解,及自定义解析器实现对象自动注入操作

    # java-SpringBoot自定义参数解析器实现对象自动注入 解析器逻辑流程图表 后台解析注解的解析器 首先,我在java后台编写了一个解析器,代码如下 import com.ruoyi.framework.interceptor.annotation.LoginUser; import com.ruoyi.project.WebMoudle.WebUser.domain.WebUser; import com.ruoyi.project.WebMoudle.WebUser.service

  • java教程之java注解annotation使用方法

    1.概述 注解可以定义到方法上,类上,一个注解相当与一个类,就相当于实例了一个对象,加上了注解,就相当于加了一个标志. 常用的注解:@Override:表示重新父类的方法,这个也可以判断是否覆盖的父类方法,在方法前面加上此语句,如果提示的错误,那么你不是覆盖的父类的方法,要是提示的没有错误,那么就是覆盖的父类的方法.@SuppressWarnings("deprecation"):取消编译器的警告(例如你使用的方法过时了)@Deprecated:在方法的最上边也上此语句,表示此方法过时

  • Java对象转json JsonFormat注解

    写在前面,首先,我用的java转json序列化的工具是java开源的jackson. 今天在做后端接口的时候,发现获取的json对象中少了几个属性,因为其他的接口都能得到正确的json,所以很快就找到了问题所在,先上代码 public class ChargeDto implements Serializable { private static final long serialVersionUID = -4617215025083571608L; protected Integer cId;

  • JAVA socket.io注解原理及用法图解

    这是一个实现了监听connect()函数的注解,类似于切面的后置通知,当用户试图建立连接后再执行,并且不论是否成功创建连接,都一定会进入的,但是在鉴权的时候返回false,则不会进入该函数.如果有机会我会开贴来重点分享一下其中的区别 @OnDisconnect 这是实现了监听disconnect()函数的注解,类似于切面的后置通知,当用户断开连接后再执行. @OnEvent("String") 这是表示下方函数用于接收前端发送端口(String)时触发的方法. socket.emit(

  • 小议Java中@param注解与@see注解的作用

    @ param @ param标签可以归档方法或构造器的某个单一参数,或者归档类.接口以及泛型方法的类型参数.在使用@ param标签时,我们应该针对方法的每一个参数都使用一个该标签.每个段落的第一个词会被当作参数名,而余下的部分则会被当作是对它的描述: @param max The maximum number of words to read. 当归档类型参数时,我们应该在类型参数名两边加上<和>: @param一e element type of this List 然而,类型参数通常并

随机推荐