java基础解析系列(六)---注解原理及使用

先来一个例子

class Father
{
public void f()
{}
}
public class Son extends Father{
@Override
public void f()
{}
}
  • 当子类重写父类的方法的时候,上面会出现一个 @Override ,这就是一个注解
@Controller
public class StudentController {
  • 框架中的@Controller也是一个注解

什么是注解

 public interface Annotation {
boolean equals(Object obj);
int hashCode();
String toString();
Class<? extends Annotation> annotationType();
}
  • 注解是一个接口
  • 从某方面看,注解的作用就像修饰符(public,final,static)一样
  • 程序可以通过反射来获取指定程序元素的Annotion,然后通过Annotion来获取注解里面的元数据。

注解的种类

  • JDK内置系统注解
  • 元注解,用于'修饰'注解
  • 自定义注解

JDK内置系统注解

@Override

  • 上面的例子已经展示,这个注解的作用是用于修饰覆盖了父类的方法

@Deprecated

  • 这个注解是用来修饰已经过时的方法

  • 可以看到当方法用@Deprecated修饰,然后使用这个方法的时候,编译器会提醒这个方法已经过时

@SuppressWarnnings

  • 用于忽略编译器警告信息,告诉编译器停止对此方法的警告。

元注解

@Target

  • 作用:被描述的注解可以用在什么地方
  • 参数值
ElementType 含义
ElementType 含义
ANNOTATION_TYPE 注解类型声明
CONSTRUCTOR 构造方法声明
FIELD 字段声明(包括枚举常量)
LOCAL_VARIABLE 局部变量声明
METHOD 方法声明
PACKAGE 包声明
PARAMETER 参数声明
TYPE 类、接口(包括注解类型)或枚举声明
import java.lang.annotation.Target;
import java.lang.annotation.ElementType; @Target(ElementType.FIELD)
public @interface MyAnnotation { }
  • 上面是自定义的一个注解,用了一个@Target来修饰,表明这个自定义注解可以用来修饰域

   

@Retention

  • 作用:指示注释类型的注释要保留多久
  • 参数值
RetentionPoicy 意义
SOURCE 源文件中保留,比如@Override,用于与编译器交互
CLASS source,Class文件保留,用于编译时生成额外的文件
RUNTIME sorce,class文件,运行时保留

@Documented

  • 作用:指示某一类型的注释将通过 javadoc 和类似的默认工具进行文档化
  • 被@Documented修饰的注解会生成到javadoc中
import java.lang.annotation.Documented;
@Documented
public @interface Demo
{ }
  • 打开cmd,然后执行javadoc Demo.java,然后可以看到这个注解生成到了javadoc

@Inherited

  • 作用:指示注释类型被自动继承。可以让子类对象使用getAnnotations()获取父类@Inherited修饰的注解。

@Inherited
@Retention( RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface MyAnnotation {
String msg() default "jiajun";
} @MyAnnotation
class Father
{ }
class son extends Father{ } public class Demo6
{
public static void main(String[] args) {
Father f=new son();
System.out.println(Arrays.toString(f.getClass().getAnnotations()));
}
}
//输出:[@MyAnnotation(msg=jiajun)]

自定义注解

格式

  • public @interface 注解名 {定义体}

@Retention源码

@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE)
public @interface Retention {
/**
* Returns the retention policy.
* @return the retention policy
*/
RetentionPolicy value();
}
  • 可以看到注解方法返回值是RetentionPolicy枚举类型

使用

  • 用@interface(区别于interface)来声明一个注解
  • 使用@interface定义注解的时候,自动继承了Annotation接口
  • 用元注解修饰自定义注解
  • 定义体里面可以定义一些参数成员,default设置默认参数值
  • 使用注解的时候,传值方式(msg=""),当参数名是value的时候,可以直接用("666")的形式传值。
  • 当没有传值的时候, @MyAnnotation(),获取到的参数值是默认值

实验

@Retention( RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface MyAnnotation {
String msg() default "jiajun";
} @MyAnnotation(msg="666")
class Test1
{}
public class Test2 { public static void main(String[] args) {
Test1 t=new Test1();
Class c=t.getClass();
MyAnnotation ma = (MyAnnotation) c.getAnnotation(MyAnnotation.class);
System.out.println(ma.msg());
} }
  • 自定义了一个MyAnnotation注解,用Retention注解声明注解的生命周期,和Target修饰该注解的修饰范围
  • Test1类用自定义的注解修饰,通过Class获取相关信息。当Rention修饰的不是RUNTIME的时候,不能获得相关信息

访问注解

访问类注解

@Retention( RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface MyAnnotation {
String name() default "jiajun";
}
@MyAnnotation(name="jiajun")
public class Test {
}
public static void main(String[] args) {
Class clazz = Test.class;
Annotation[] annotations = clazz.getAnnotations();
for(Annotation annotation : annotations){
if(annotation instanceof MyAnnotation){
MyAnnotation myAnnotation = (MyAnnotation) annotation;
System.out.println("name: " + myAnnotation.name());
}
}
}

访问方法注解

@Retention( RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface MyAnnotation {
String name() default "jiajun";
} public class Test {
@MyAnnotation(name="jiajun")
public void doSomething(){}
} public class Demo {
public static void main(String[] args) {
Class clazz=Test.class;
Method[] methods=clazz.getMethods();
for(Method method :methods)
{
if(method.getName()=="doSomething")
{
Annotation annotation = method.getAnnotation(MyAnnotation.class);
if(annotation instanceof MyAnnotation){
MyAnnotation myAnnotation = (MyAnnotation) annotation;
System.out.println("name: " + myAnnotation.name());
}
}
}
}
}

访问参数注解

@Retention( RetentionPolicy.RUNTIME)
@Target(ElementType.PARAMETER)
public @interface MyAnnotation {
String name() default "jiajun";
}
public class Test {
public static void doSomething(
@MyAnnotation(name="jiajun") String parameter){
}
}
public class Demo {
public static void main(String[] args) {
Class clazz=Test.class;
Method[] methods=clazz.getMethods();
for(Method method :methods)
{
if(method.getName()=="doSomething")
{
Annotation[][] parameterAnnotations = method.getParameterAnnotations();
Class[] parameterTypes = method.getParameterTypes(); int i=0;
for(Annotation[] annotations : parameterAnnotations){
Class parameterType = parameterTypes[i++]; for(Annotation annotation : annotations){
if(annotation instanceof MyAnnotation){
MyAnnotation myAnnotation = (MyAnnotation) annotation;
System.out.println("param: " + parameterType.getName());
System.out.println("name : " + myAnnotation.name());
}
}
}
}
}
}
}
  • 每个方法有n个参数,每个参数包含一个注解数组,因此getParameterAnnotations()返回的是一个二维数组

我觉得分享是一种精神,分享是我的乐趣所在,不是说我觉得我讲得一定是对的,我讲得可能很多是不对的,但是我希望我讲的东西是我人生的体验和思考,是给很多人反思,也许给你一秒钟、半秒钟,哪怕说一句话有点道理,引发自己内心的感触,这就是我最大的价值。(这是我喜欢的一句话,也是我写博客的初衷)

作者:jiajun 出处: http://www.cnblogs.com/-new/

本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。如果觉得还有帮助的话,可以点一下右下角的【推荐】,希望能够持续的为大家带来好的技术文章!想跟我一起进步么?那就【关注】我吧。

java基础解析系列(六)---深入注解原理及使用的更多相关文章

  1. java基础解析系列(六)---注解原理及使用

    java基础解析系列(六)---注解原理及使用 java基础解析系列(一)---String.StringBuffer.StringBuilder java基础解析系列(二)---Integer缓存及 ...

  2. java基础解析系列(四)---LinkedHashMap的原理及LRU算法的实现

    java基础解析系列(四)---LinkedHashMap的原理及LRU算法的实现 java基础解析系列(一)---String.StringBuffer.StringBuilder java基础解析 ...

  3. java基础解析系列(七)---ThreadLocal原理分析

    java基础解析系列(七)---ThreadLocal原理分析 目录 java基础解析系列(一)---String.StringBuffer.StringBuilder java基础解析系列(二)-- ...

  4. java基础解析系列(八)---fail-fast机制及CopyOnWriteArrayList的原理

    fail-fast机制及CopyOnWriteArrayList的原理 目录 java基础解析系列(一)---String.StringBuffer.StringBuilder java基础解析系列( ...

  5. java基础解析系列(九)---String不可变性分析

    java基础解析系列(九)---String不可变性分析 目录 java基础解析系列(一)---String.StringBuffer.StringBuilder java基础解析系列(二)---In ...

  6. java基础解析系列(十)---ArrayList和LinkedList源码及使用分析

    java基础解析系列(十)---ArrayList和LinkedList源码及使用分析 目录 java基础解析系列(一)---String.StringBuffer.StringBuilder jav ...

  7. java基础解析系列(十一)---equals、==和hashcode方法

    java基础解析系列(十一)---equals.==和hashcode方法 目录 java基础解析系列(一)---String.StringBuffer.StringBuilder java基础解析系 ...

  8. java基础解析系列(五)---HashMap并发下的问题以及HashTable和CurrentHashMap的区别

    java基础解析系列(五)---HashMap并发下的问题以及HashTable和CurrentHashMap的区别 目录 java基础解析系列(一)---String.StringBuffer.St ...

  9. java基础解析系列(二)---Integer

    java基础解析系列(二)---Integer 前言:本系列的主题是平时容易疏忽的知识点,只有基础扎实,在编码的时候才能更注重规范和性能,在出现bug的时候,才能处理更加从容. 目录 java基础解析 ...

随机推荐

  1. 借助VBScript让Windows系统发出声音

    借助VBScript让Windows系统发出声音.. 文件I Love You.VBS中的内容是: CreateObject("SAPI.SpVoice").Speak" ...

  2. Nginx入门案例(Mac版)

    Nginx(engine x)是一个轻量级.高性能的Web和反向代理服务器,也是一个IMAP.POP3和SMTP服务器,并且安装十分简单,配置文件非常简洁,启动特别容易,运行十分稳定,几乎可以做到7* ...

  3. 一个还算简单的微信消息SDK(基于.Net Standard 2.0)

    虽然微信公众号出现了好久,不过在SDK这件事情上感觉并没有多少人把它当成一个有技术含量的事情来做,很多SDK做的事情就是一个代码的堆叠,当然也可能写的好的并没有开源出来.所以在某个翻遍Github而无 ...

  4. XMind与MindManager哪个好(网易云课堂老师:Array老师讲解稿)

    XMind与MindManager哪个好 作者:网易云课堂老师:Array老师讲解稿 思维导图是一种将放射性思考具体化的方法,可以将人们的创造性思维及时捕捉并呈现,深受商业人士的喜爱.目前,XMind ...

  5. 后端路由项目由 gulp 改为 webpack 的踩坑实录

    前言 公司有个后端路由的项目是用 gulp 作为前端自动化构建工具,最近学习了一下 webpack,深感其强大,一狠心将其改成了 webpack 构建,以下是踩坑实录. gulp 先来说说原来的架构. ...

  6. JavaScript在应用中的技巧(一)

    分享一些在JavaScript中遇到的一些实用的技巧. 理解JavaScript的数值型数据类型 JavaScript的数值型数据类型只有一种:number.即不管是整数还是浮点数,JavaScrip ...

  7. Ibatis XML 配置文件注释引起错误及解决方案

    详见:http://blog.yemou.net/article/query/info/tytfjhfascvhzxcytp35 Ibatis XML 配置文件注释引起错误及解决方案 最近在使用Iba ...

  8. Python闭包及其作用域

    Python闭包及其作用域 关于Python作用域的知识在python作用域有相应的笔记,这个笔记是关于Python闭包及其作用域的详细的笔记 如果在一个内部函数里,对一个外部作用域(但不是全局作用域 ...

  9. Apache配置虚拟域名

    在作php本地调试的时候,一般都要打上localhost/,如果你的项目层级关系比较多,那你的url地址就会很长. 那我们能不能用一个简短的域名去替代那些一长串无用的字符呢? 那可能有人会问如果我没有 ...

  10. 团队作业6——展示博客(Alpha)

    一.团队简介 李永豪(PM):项目经理,后台开发人员,协调团队内部的工作及开发团队之间的工作 杨海亮:后台开发人员,测试人员,熟悉java语言,编写java代码 郑靖涛:后台开发人员,测试人员,安卓程 ...