你说啥什么?注解你还不会?
注解
文末有彩蛋。
一、什么是注解?
Annotaion
注解(Annotaion)
是从JDK5.0开始引入的一种新技术称之为注解机制。注解(Annotaion)
的格式:- 注解是以"
@注释名
"在代码中使用的,可以添加一些参数值,例如:@GetMapping("/get")
- 注解是以"
注解(Annotaion)
可以使用的范围:可以在package、class、method、field等上面使用。例如:
@Controller public class RequestController {@DeleteMapping("/delete")@ResponseBodypublic String delete(String name,Integer id){JSONObject json = new JSONObject();json.put("requestType","deleteType");json.put("name",name);json.put("id",id);return json.toString();}}
我们可以通过反射机制编程对这些元数据的访问。
注解有一些特定的功能,例如:
当你如果要重写toString()方法的时候,不是按照规定的名字来写的话,就会报错:
正常的话,是不会报错的:
说明
@Override
注解带有检查的作用。
二、内置注解
Java内部定义了一套注解,共有7个:
注解名称 | 作用 |
---|---|
@Override | 检查该方法是否是重写方法。如果发现其父类,或者是引用的接口中并没有该方法时,会报编译错误。 |
@Deprecated | 标记过时方法。如果使用该方法,会报编译警告。 |
@SuppressWarnings | 指示编译器去忽略注解中声明的警告。 |
作用在其他注解的注解(元注解
):在java.lang.annotaion
包中
注解名称 | 作用 |
---|---|
@Retention | 标识这个注解怎么保存,是只在代码中,还是编入class文件中,或者是在运行时可以通过反射访问。 |
@Documented | 标记这些注解是否包含在用户文档中。 |
@Target | 标记这个注解应该是哪种 Java 成员。 |
@Inherited | 标记这个注解是继承于哪个注解类(默认 注解并没有继承于任何子类) |
从 Java 7 开始,额外添加了 3 个注解:
注解名称 | 作用 |
---|---|
@SafeVarargs | Java 7 开始支持,忽略任何使用参数为泛型变量的方法或构造函数调用产生的警告。 |
@FunctionalInterface | Java 8 开始支持,标识一个匿名函数或函数式接口。 |
@Repeatable | Java 8 开始支持,标识某注解可以在同一个声明上使用多次。 |
三、元注解的使用
(一)前期准备
如果
你想自定义注解
,那么元注解是必知必会必懂
的。
元注解就是注解自定义注解的注解
。可能有点饶,一会看例子就明白了,直白点就是给你自定义的注解上一定要加的注解
。
作用在其他注解的注解(元注解
):在java.lang.annotaion
包中
注解名称 | 作用 |
---|---|
@Retention | 标识这个注解怎么保存,是只在代码中,还是编入class文件中,或者是在运行时可以通过反射访问。 |
@Documented | 标记这些注解是否包含在用户文档中。 |
@Target | 标记这个注解应该是哪种 Java 成员。 |
@Inherited | 标记这个注解是继承于哪个注解类(默认 注解并没有继承于任何子类) |
我们定义一个类,类的作用就是用来测试我们定义的注解:
/*** @Auther: truedei* @Date: 2020 /2020/9/6 18:11* @Description: 自定义注解测试*/
public class Test {}
然后创建一个类,把class标识符改成@interface
:这就是自定义好的注解了。
/*** @Auther: truedei* @Date: 2020 /2020/9/6 19:00* @Description: 自定义注解*/
public @interface MyAnnotaion {}
现在可以看到就可以使用了,只不过没有任何的功能:
(二)@Target的用法详解
我们来赋予一定的功能,来标识这个注解的作用:
加上元注解:@Target,就是用来指出对什么生效,作用的目标是什么,可以在什么地方使用。
可以看到传递的是一个E
可以点看@Target的源码看一下:
可以看到下面这种情况。
需要提前知道的是,
value()
是接收的参数,并不是一个方法。那么Target就需要接收一个
ElementType[]
的数组。
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE)
public @interface Target {ElementType[] value();
}
没加之前,先改造一下:
可以看到这个注解什么都没加,既可以加在类上,也可以加在方法上,也可以加在变量上。
如果我们想做限制呢?只允许我们的这个注解对类生效
我们先来看一下Controller注解
这个应该不陌生,就不解释了。
那么我们也可以加上这个:
可以看到效果了,只要类上的生效了,其余的都报错了。
那么这就是元注解Target的作用。
看一下ElementType.java
中枚举的参数,这些都可以使用,了解下就好。
package java.lang.annotation;public enum ElementType {TYPE, /* 类、接口(包括注释类型)或枚举声明 */FIELD, /* 字段声明(包括枚举常量) */METHOD, /* 方法声明 */PARAMETER, /* 参数声明 */CONSTRUCTOR, /* 构造方法声明 */LOCAL_VARIABLE, /* 局部变量声明 */ANNOTATION_TYPE, /* 注释类型声明 */PACKAGE /* 包声明 *//*** Type parameter declaration** @since 1.8*/TYPE_PARAMETER,/*** Use of a type** @since 1.8*/TYPE_USE
}
如果你想让你的注解对什么生效,就指定好就OK:
(三)@Retention的用法详解
Retention中需要传递RetentionPolicy。
RetentionPolicy.java
有三个枚举参数,如下:
package java.lang.annotation;
public enum RetentionPolicy {SOURCE, /* Annotation信息仅存在于编译器处理期间,编译器处理完之后就没有该Annotation信息了 */CLASS, /* 编译器将Annotation存储于类对应的.class文件中。默认行为 */RUNTIME /* 编译器将Annotation存储于class文件中,并且可由JVM读入 */
}
一般都是调用**RUNTIME
**,调用RUNTIME
我们可以通过反射拿到相关的数据,来进行处理等。
由于这个不太好验证,就不一一验证了,了解就好
。
(四)@Documented的用法详解
如果使用 @Documented 修饰该 Annotation,则表示它可以出现在 javadoc 中。
定义 Annotation 时,@Documented 可有可无;
若没有定义,则 Annotation 不会出现在 javadoc 中。
(五)@Inherited的用法详解
子类可以继承父类的注解。
/*** @Auther: truedei* @Date: 2020 /2020/9/6 19:00* @Description: 自定义注解*/
@Target({ElementType.TYPE,ElementType.FIELD,ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
public @interface MyAnnotaion {}
四、自定义参数详解
注解的参数:参数的类型 + 参数名 ();
如果想有默认值还需要加上default 值。
例如:
//自定义参数1
String name();
//自定义参数2 带默认值的
String type() default "";
我们给事先定义好的注解类加上一个参数,随便写名字即可:
@Target({ElementType.TYPE,ElementType.FIELD,ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
public @interface MyAnnotaion {//参数String name();}
可以看到我们在使用的时候,就会报错了,原因是必须要给这个定义好的参数传递一个值。
我们传递过来值:
@MyAnnotaion(name = "郑晖")
public void test(){}
这个时候就有同学要问了:我定义好参数之后,可以不传递参数吗,用到的时候再传递。
答案是可以的,如下:设置一个默认值就好了:
String type() default "";
当然了,也可以传递很多类型的参数例如:
import java.lang.annotation.*;/*** @Auther: truedei* @Date: 2020 /2020/9/6 19:00* @Description: 自定义注解*/
@Target({ElementType.TYPE,ElementType.FIELD,ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
public @interface MyAnnotation {//String类型String name();//int类型int age() default 0;//boolean类型boolean bool() default false;//char 类型char cha() default ' ';//各种数组类型String[] strs() default {};//枚举类型MyEnum myEnum() default MyEnum.A;}
枚举类型类定义:
public enum MyEnum {A,B,C,D;
}
我们在使用的时候,就可以随心所欲的使用:
/*** @Auther: truedei* @Date: 2020 /2020/9/6 18:11* @Description: 自定义注解测试*/
public class Test {String data;@MyAnnotaion(name = "郑晖",age = 85,cha = 'A',strs = {"aasd","xsw","你好"},myEnum = MyEnum.C)public void test(){}}
五、利用反射操作注解
MyA.java:
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 MyA {}
MyAnnotation.java:
import java.lang.annotation.*;/*** @Auther: truedei* @Date: 2020 /2020/9/6 19:00* @Description: 自定义注解 ---->给特定的方法用的*/
@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface MyAnnotation {//String类型String name();}
Test.java:
/*** @Auther: truedei* @Date: 2020 /2020/9/6 18:11* @Description: 自定义注解测试*/
@MyA
public class Test {String data;@MyAnnotation(name = "郑晖")public void test(String name){System.out.println("我的名字:"+name);}}
测试类:
package cn.annotaion;import java.lang.annotation.Annotation;
import java.lang.annotation.Target;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Inherited;
import java.lang.reflect.Method;
/**
*测试类
*/
public class AnnotationTest {public static void main(String[] args) throws Exception {//拿到指定的类的TestClass cl = Class.forName("cn.annotaion.Test");//判断是否是我们特定自定义的注解 如果是就扫描if (cl.isAnnotationPresent(MyA.class)) {Method[] methods = cl.getMethods();for (Method method : methods) {// 判断 somebody() 方法是否包含MyAnnotation注解if(method.isAnnotationPresent(MyAnnotation.class)){// 获取该方法的MyAnnotation注解实例MyAnnotation myAnnotation = method.getAnnotation(MyAnnotation.class);// 获取 myAnnotation的值,并打印出来String name = myAnnotation.name();System.out.println(name);//执行这个方法method.invoke(new Test(),name);}}}}}
运行:
六、彩蛋
看完了之后,发现有什么问题吗?
细心的你一定注意到:最初我使用的是MyAnnotaion.java
后来MyAnnotation.java
没错,少写了个t
。还好不影响大局。
你说啥什么?注解你还不会?相关推荐
- @data注解不生效_你说啥什么?注解你还不会?
点击蓝色字免费订阅,每天收到这样的好信息 前言:最近有不少粉丝关注本公众号.并且我已经成功开通了流量主同时会赚一点点广告费,我打算每个月把这部分钱拿出来给大家买点书刊,算是给大家一点福利吧.大家想买什 ...
- Spring中@Autowired注解、@Resource注解的区别
Spring不但支持自己定义的@Autowired注解,还支持几个由JSR-250规范定义的注解,它们分别是@Resource.@PostConstruct以及@PreDestroy. @Resour ...
- 扒一扒 @SpringBootApplication 注解背后的奥秘!
点击上方蓝色"方志朋",选择"设为星标" 回复"666"获取独家整理的学习资料! 概 述 Spring Boot的约定大于配置的功力让我们如 ...
- java自定义注解简单小例子
接上例子,新建Java Project 1.新建Interface,建完在名字前加@,就成了自定义的注解 [java] view plaincopy import java.lang.annotati ...
- 浅谈Java/Android下的注解
什么是注解 java.lang.annotation,接口 Annotation,在JDK5.0及以后版本引入. 注解是代码里的特殊标记,这些标记可以在编译.类加载.运行时被读取,并执行相应的处理.通 ...
- Spring注解Annotation
1. 使用Spring注解来注入属性 1.1. 使用注解以前我们是怎样注入属性的 类的实现: Java代码 public class UserManagerImpl implements Use ...
- Spring注解标签详解@Autowired @Qualifier等
@Autowired spring2.1中允许用户通过@Autowired注解对Bean的属性变量.属性Setter方法以及构造函数进行标注,配合AutowiredAnnotationBeanProc ...
- Java程序员从笨鸟到菜鸟之(七十二)细谈Spring(四)利用注解实现spring基本配置详解
注:由于本人不大习惯注解方式,所以讲解完这里的注解实现基本配置之后,以后就不再单独把注解拿出来讲解了. 五:spring注解 1.准备工作 (1)导入common-annotations.jar (2 ...
- java指导手册,Java 注解指导手册 – 终极向导
编者的话:注解是java的一个主要特性且每个java开发者都应该知道如何使用它. 现在,是时候汇总这些和注解相关的信息到一篇文章了,祝大家阅读愉快. 目录 什么是注解 介绍 消费器 注解语法和注解元素 ...
最新文章
- 为NLP从业者/研究生/研究员专门定制的全网唯一高端NLP训练营
- 使用vue-router设置每个页面的title
- xml学习总结(四)
- linux popd 命令,Linux中的pushd推入和popd弹出命令
- 最小生成树(Kruskal算法+Prim算法)简单讲解+最小生成树例题 acm寒假集训日记22/1/8
- Django 系列博客(十一)
- e: 无法定位软件包 python-pip_关于Sony镜头不同系列定位的最全面分析
- Android 自定义标尺滑动选择值
- Android Builder模式
- python3超简代码爬取桌面壁纸
- 蓝桥杯,基础练习 Fibonacci数列(斐波那契数列) C++
- git命令 之 切糕大全
- 如何使用 win10 虚拟桌面
- vue之设置背景图片自适应屏幕
- 心电图心电轴怎么计算_心电轴的测量方法
- 计算机系统软件最核心软件是,安徽电脑加密软件哪个好-防止泄密
- vue-router 是什么?它有哪些组件
- linux 字符串数组初始化,Linux命令行 – 数组
- 清除浮动的常用的几种方法
- C#编程学习(07):自动监测大写键是否被锁定
热门文章
- 使用python爬取招聘网站数据
- 闲来没事自己研究了下RBAC
- 计算机机房 网络安全,机房网络安全建设标准参考
- matlab ecu代码,嵌入式代码生成 - 汽车 ECU 产品级代码 - MATLAB Simulink
- 《PyCharm2019安装教程》
- JAVA核心知识点--JDK1.8中的日期处理
- 卫星遥感在农业干旱方面最新研究
- java发送图片邮件_使用javamail发送包含图片的html格式邮件详解
- yarn : 无法加载文件 C:\Users\HYGK\AppData\Roaming\npm\yarn.ps1,因为在此系统上禁止运行脚本。有关详细信息,请参阅 https:/go.microsof
- java 实例化异常_如何处理实例化类对象时发生的异常