java系列之注解

我们在实际项目开发中使用注解的目的:为了追求低耦合,降低后期的维护成本。平时自己在实际项目也会经常用到注解,所以想着自己总结一下注解的知识点,毕竟"好记性不如烂笔头",忘记的时候可以自己打开文章梳理一下,下面开始进入正文。

一、注解的本质:

从源码角度分析

[java.lang.annotation.Annotation」接口中有这么一句话,用来描述『注解』。
The common interface extended by all annotation types.
翻译成中文:所有的注解类型都继承自这个普通的接口(Annotation)

举个简单的例子理解一下,平时开发中我们使用最多的就是@Overrider注解,实际上该注解的基类是annotation接口;

//用代码描述即如下:
public interface Override extends Annotation{

}

关于上述代码,有感兴趣的伙伴们可以找到内置java注解,反编译验证。

因此,java注解中不能支持继承其他类或接口。

二、注解:

  2.1注解解析

解析一个类或者方法的注解往往有两种形式,一种是编译期直接的扫描,一种是运行期反射。

编译器的扫描指的是编译器在对 java 代码编译字节码的过程中会检测到某个类或者方法被一些注解修饰,这时它就会对于这些注解进行某些处理。

典型的就是注解 @Override,一旦编译器检测到某个方法被修饰了 @Override 注解,编译器就会检查当前方法的方法签名是否真正重写了父类的某个方法,也就是比较父类中是否具有一个同样的方法签名。这一种情况只适用于那些编译器已经熟知的注解类,比如 JDK 内置的几个注解,而你自定义的注解,编译器是不知道你这个注解的作用的,当然也不知道该如何处理,往往只是会根据该注解的作用范围来选择是否编译进字节码文件,仅此而已。

  2.2注解支持的数据类型

  • 所有基本类型(int,float,boolean,byte,double,char,long,short)
  • String
  • Class
  • enum
  • Annotation
  • 上述类型的数组

  倘若使用了其他数据类型,编译器将会丢出一个编译错误,注意,声明注解元素时可以使用基本类型但不允许使用任何包装类型。

三、元注解:

元注解的定义:可以理解为用于修饰注解的注解,通常用于注解的定义上。例如,从源码举例:

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.SOURCE)
public @interface Override {

}

  其中@Target、@Retention便是元注解,主要用于定义注解的生命周期和作用目标等信息;

下面主要介绍一下元注解:

[email protected]

  @Target:注解的作用目标:用于指明被修饰的注解最终可以作用的目标是谁,也就是指明,你的注解到底是用来修饰方法的?修饰类的?还是用来修饰字段属性的。

     源码定义:

  

  用法:

@Target(value = {ElementType.FIELD})

  从源码中可以看到target注解中存在一个ElementType类型的value,那么我们进入这个枚举里面看下:

public enum ElementType {
    /**标明该注解可以用于类、接口(包括注解类型)或enum声明*/
    TYPE,
    /** 标明该注解可以用于字段(域)声明,包括enum实例 */
    FIELD,
    /** 标明该注解可以用于方法声明 */
    METHOD,
    /** 标明该注解可以用于参数声明 */
    PARAMETER,
    /** 标明注解可以用于构造函数声明 */
    CONSTRUCTOR,
    /** 标明注解可以用于局部变量声明 */
    LOCAL_VARIABLE,
    /** 标明注解可以用于注解声明(应用于另一个注解上)*/
    ANNOTATION_TYPE,
    /** 标明注解可以用于包声明 */
    PACKAGE,
    /**
     * 标明注解可以用于类型参数声明(1.8新加入)
     * @since 1.8
     */
    TYPE_PARAMETER,
    /**
     * 类型使用声明(1.8新加入)
     * @since 1.8
     */
    TYPE_USE
}

[email protected]:

  @Retention 用于指明当前注解的生命周期;

  源码定义:

  

  用法:

@Retention(value = RetentionPolicy.RUNTIME)

  同理,该元注解依然存在一个枚举类型的value,我们跟进源码中分析:

public enum RetentionPolicy {
    /**
     * 当前注解编译期可见,不会写入 class 文件(该类型的注解信息只会保留在源码里,源码
     *经过编译后,注解信息会被丢弃,不会保留在编译好的class文件里)
     */
    SOURCE,

    /**
     * 类加载阶段丢弃,会写入 class 文件(该类型的注解信息会保留在源码里和class文件
     * 里,在执行的时候,不会加载到虚拟机中)
    */
    CLASS,

    /**
     * 永久保存,可以反射获取(源码、class文件和执行的时候都有注解的信息)
     * @see java.lang.reflect.AnnotatedElement
     */
    RUNTIME
}

  总之,@Retention 注解指定了被修饰的注解的生命周期。

  3.2.1只能在编译期可见,编译后会被丢弃;

  3.2.2会被编译器编译进 class 文件中,无论是类或是方法,乃至字段,他们都是有属性表的,而 JAVA 虚拟机也定义了几种注解属性表用于存储注解信息,但是这种可见性不能带到方法区,类加载时会予以丢弃,有感兴趣的可以百度虚拟机相关知识了解;

  3.2.3永久存在的可见性。

四、java内置注解:

@Override:用于标明此方法覆盖了父类的方法,源码如下

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.SOURCE)
public @interface Override {
}

  它没有任何的属性,所以并不能存储任何其他信息。它只能作用于方法之上,编译结束后将被丢弃。

  它就是一种典型的『标记式注解』,仅被编译器可知,编译器在对 java 文件进行编译成字节码的过程中,一旦检测到某个方法上被修饰了该注解,就会去匹对父类中是否具有一个同样方法签名的函数,如果不是,自然不能通过编译。

@Deprecated:用于标明已经过时的方法或类,源码如下,关于@Documented稍后分析:

@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(value={CONSTRUCTOR, FIELD, LOCAL_VARIABLE, METHOD, PACKAGE, PARAMETER, TYPE})
public @interface Deprecated {
}

依然是一种『标记式注解』,永久存在,可以修饰所有的类型,作用是,标记当前的类或者方法或者字段等已经不再被推荐使用了,可能下一次的 JDK 版本就会删除。

当然,编译器并不会强制要求你做什么,只是告诉你 JDK 已经不再推荐使用当前的方法或者类了,建议你使用某个替代者。

@SuppressWarnnings:用于有选择的关闭编译器对类、方法、成员变量、变量初始化的警告,其实现源码如下:

@Target({TYPE, FIELD, METHOD, PARAMETER, CONSTRUCTOR, LOCAL_VARIABLE})
@Retention(RetentionPolicy.SOURCE)
public @interface SuppressWarnings {
String[] value();
}

其内部有一个String数组,value 属性需要你主动的传值,这个 value 代表一个什么意思呢,这个 value 代表的就是需要被压制的警告类型。

主要接收值如下:

deprecation:使用了不赞成使用的类或方法时的警告;
unchecked:执行了未检查的转换时的警告,例如当使用集合时没有用泛型 (Generics) 来指定集合保存的类型;
fallthrough:当 Switch 程序块直接通往下一种情况而没有 Break 时的警告;
path:在类路径、源文件路径等中有不存在的路径时的警告;
serial:当在可序列化的类上缺少 serialVersionUID 定义时的警告;
finally:任何 finally 子句不能正常完成时的警告;
all:关于以上所有情况的警告。

原文地址:https://www.cnblogs.com/wx_blog/p/12641648.html

时间: 2024-11-26 11:45:57

java系列之注解的相关文章

我爱java系列---【自定义注解】

一.注解概述 1.定义:注解(Annotation),也叫元数据.一种代码级别的说明.它是JDK1.5及以后版本引入的一个特性,与类. 接口.枚举是在同一个层次.它可以声明在包.类.字段.方法.局部变量.方法参数等的前面,用来对这些元素 进行说明,注释. 2.作用分类: 编写文档:通过代码里标识的注解生成文档[例如,生成文档doc文档] 代码分析:通过代码里标识的注解对代码进行分析[例如,注解的反射] 编译检查:通过代码里标识的注解让编译器能够实现基本的编译检查[例如,Override] 3.常

Java学习系列(二十一)Java面向对象之注解详解

转载请注明出处:http://blog.csdn.net/lhy_ycu/article/details/45295947 一.前言 Java中的注解Annotation运用到很多方面,比如之前讲的单元测试中的@Test.Spring.SpringMVC还有其他框架等等.Java本身自带的注解也有一些,比如:@Override(子类要重写/覆写父类的对应方法).@Deprecated(表示方法不建议被使用).@SuppressWarnings(抑制警告)等等.当然,我们也可以自定义一些自己需要的

Java系列(1)----Java特性

一.Java的关键特性1.简单性2.安全性3.可移植性4.面向对象5.健壮性6.多线程7.体系结构中立8.解释执行9.高性能10.分布式11.动态性 二.J2SE 5的主要特性1.泛型2.注解(annotation)3.自动装箱和自动拆箱4.枚举5.增强for-each风格的for循环6.可变长度参数7.静态导入8.格式化I/O9.并发实用工具 三.J2SE 7的重要特性1.String现在能够控制switch语句2.二进制整型字面值3.数值字面值下的下划线4.扩展的try语句,称为带资源的tr

【JAVA系列】Google爬虫如何抓取JavaScript的?

公众号:SAP Technical 本文作者:matinal 原文出处:http://www.cnblogs.com/SAPmatinal/ 原文链接:[JAVA系列]Google爬虫如何抓取JavaScript的? 前言部分 大家可以关注我的公众号,公众号里的排版更好,阅读更舒适. 正文部分 我们测试了谷歌爬虫是如何抓取 JavaScript,下面就是我们从中学习到的知识. 认为 Google 不能处理 JavaScript ?再想想吧.Audette Audette 分享了一系列测试结果,他

Java系列笔记(1) - Java 类加载与初始化

目录 类加载器 动态加载 链接 初始化 示例 类加载器 在了解Java的机制之前,需要先了解类在JVM(Java虚拟机)中是如何加载的,这对后面理解java其它机制将有重要作用. 每个类编译后产生一个Class对象,存储在.class文件中,JVM使用类加载器(Class Loader)来加载类的字节码文件(.class),类加载器实质上是一条类加载器链,一般的,我们只会用到一个原生的类加载器,它只加载Java API等可信类,通常只是在本地磁盘中加载,这些类一般就够我们使用了.如果我们需要从远

Java高级之注解、反射

Java的注解.反射等机制的产生,让动态代理成为可能,一般通过全限定名+类名,找到类,可以invoke它的构造方法以及其他方法,可以获取它的参数(Field)名称和值. 注解一般用在代码的注释上.代码审查上(有没有按标准写,比如inspect).代码注入(hook,asbectj),需要考虑的是,在何时注入(编译期还运行期) 反射一般用在动态将json和Object互相转化,执行相关底层代码,比如设置某个类的Accessible为false,防止别人hook修改 例:阿里的FastJson解析:

Java系列笔记(2) - Java RTTI和反射机制

目录 前言 传统的RTTI 反射 反射的实现方式 反射的性能 反射与设计模式 前言 并不是所有的Class都能在编译时明确,因此在某些情况下需要在运行时再发现和确定类型信息(比如:基于构建编程,),这就是RTTI(Runtime Type Information,运行时类型信息). 在java中,有两种RTTI的方式,一种是传统的,即假设在编译时已经知道了所有的类型:还有一种,是利用反射机制,在运行时再尝试确定类型信息. 本文主要讲反射方式实现的RTTI,建议在阅读本文之前,先了解类的加载机制(

【java】java中的注解(Annotation)是如何工作的?

Java中的注解是如何工作的? 自Java5.0版本引入注解之后,它就成为了Java平台中非常重要的一部分.开发过程中,我们也时常在应用代码中会看到诸如@Override,@Deprecated这样的注解.这篇文章中,我将向大家讲述到底什么是注解,为什么要引入注解,注解是如何工作的,如何编写自定义的注解(通过例子),什么情况下可以使用注解以及最新注解和ADF(应用开发框架).这会花点儿时间,所以为自己准备一杯咖啡,让我们来进入注解的世界吧. 什么是注解? 用一个词就可以描述注解,那就是元数据,即

java系列课程精品推荐

深入学习ExtJs4.1的布局及常用控件 http://edu.ibeifeng.com/view-index-id-129.html 专题-深入Java OOP编程 http://edu.ibeifeng.com/view-index-id-88.html 案例:Red5 & Flex聊天室架构与实现 http://edu.ibeifeng.com/view-index-id-84.html 深入学习Java图表组件JFreeChart开发统计图表 http://edu.ibeifeng.co