前言
月是一轮明镜,晶莹剔透,代表着一张白纸(啥也不懂)
央是一片海洋,海乃百川,代表着一块海绵(吸纳万物)
泽是一柄利剑,千锤百炼,代表着千百锤炼(输入输出)
月央泽,学习的一种过程,从白纸->吸收各种知识->不断输入输出变成自己的内容
希望大家一起坚持这个过程,也同样希望大家最终都能从零到零,把知识从薄变厚,再由厚变薄!
一.注解是什么?
1.注解的定义
其实注解的定义,百度或者专业的人都解释的很清晰,这里小编为了防止刚学习的自己不够严谨直接摘抄了一个小编认为还很清晰的一个关于注解的定义:
Annontation是Java5开始引入的新特征,中文名称叫注解.他提供了一种安全的类似注释的机制,用来将任何信息或者元数据(metadata)与程序元素(类,方法,成员变量等)进行关联.为程序的元素(类,方法,成员变量) 加上更直观更明了的说明,这些说明信息是与程序的业务逻辑无关,并且供指定的工具或框架使用.Annontation像一种修饰符一样,应用于包,类型,构造方法,成员变量,参数及本地变量的生命语句中.
Java注解是附加在代码中的一些元信息,用于一些工具在编译,运行时进行解析和使用,起到说明,配置的功能.注解不会也不能影响代码的实际逻辑,仅仅起到辅助性的作用
2.注解的原理
注解本质是一个继承了Annotation的特殊接口,其具体实现类是Java运行时生成的动态代理类.而我们通过反射获取注解时,放回的是Java运行时生成的动态代理对象$Proxy1.通过代理对象调用自定义注解(接口)的方法,会最终调用AoontationInvocationHandler的invoke方法,该方法会从memberValues这个Map中索引出对应的值,而memberValues的来源是Java常量池.
3.注解的分类
1.元注解:注解的注解,可以为注解添加信息描述,主要是用于自定义的注解,元注解在JDK中已被定义.
2.元注解包括@Target(注解的位置),@Retention(注解的作用范围),@Documented(可以提取到javadoc,文档抽取),@Inherited(确认继承关系),@Native(确认某些内容可能来着本地代码中,比如C,或C++),@Repeatable(确认注解是否可重复.1.8时出),下面对以上元注解一一进行解释:
@Target
a.用法:用于设定注解的使用范围
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE)
public @interface Target {
/**
* Returns an array of the kinds of elements an annotation type
* can be applied to.
* @return an array of the kinds of elements an annotation type
* can be applied to
*/
ElementType[] value();
}
b.Target通过ElementType来指定注解可使用的范围
public enum ElementType {
/** Class, interface (including annotation type), or enum declaration */
//标明该注解可以用于类,接口(包括注解类型)或enum声明
TYPE,
/** Field declaration (includes enum constants) */
//标明该注解可以用于字段(域)声明,包括enum实例
FIELD,
/** Method declaration */
//标明该注解可以用于方法声明
METHOD,
/** Formal parameter declaration */
//标明该注解可以用于参数声明
PARAMETER,
/** Constructor declaration */
//标明该注解可以用于构造函数声明
CONSTRUCTOR,
/** Local variable declaration */
//标明注解可以用于局部变量声明
LOCAL_VARIABLE,
/** Annotation type declaration */
//标明注解可以用于注解声明(应用于另一个注解上)
ANNOTATION_TYPE,
/** Package declaration */
//注明注解可以用于包声明
PACKAGE,
/**
* Type parameter declaration
*
* @since 1.8
*/
//标明注解可以用于类型参数声明
TYPE_PARAMETER,
/**
* Use of a type
*
* @since 1.8
*/
//类型使用声明
TYPE_USE
特别注意:@Target缺省时,默认是支持全部的ElementType类型
其中,比较特别的两种,小编在这里单独提一下(其他的都是字面意思理解)
a).ElementType.PACKAGE.这个并不是简单的使用在一般类中,而是用在固定的文件package-info.java(而且命名一定是它)中
b).ElementType.TYPE_USE和Element.TYPE_PARAMETER两种java1.8新加入的两种,以前的注解是没有在方法类来进行的,现在加入了类型注解,让注解的应用更加广泛
@Retention
a.用法:作用于一个注解,标明当前注解能够保留到什么时候,表明一个注解的生命周期.缺省时默认为RetentionPolicy.CLASS
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE)
public @interface Retention {
/**
* Returns the retention policy.
* @return the retention policy
*/
RetentionPolicy value();
}
b.Retention的保留策略是由RetentionPolicy类中定义:
public enum RetentionPolicy {
/**
* Annotations are to be discarded by the compiler.
* 注解在被编译时被抛弃
*/
SOURCE,
/**
* Annotations are to be recorded in the class file by the compiler
* but need not be retained by the VM at run time. This is the default
* behavior.
* 被保留在class文件中,但不需要在运行时被虚拟机保留
* 这是默认的保留策略
*/
CLASS,
/**
* Annotations are to be recorded in the class file by the compiler and
* retained by the VM at run time, so they may be read reflectively.
*一直保留在运行时,而且可以被反射获取
* @see java.lang.reflect.AnnotatedElement
*/
RUNTIME
}
@Documented
a.用法:具有该类型的注解默认情况下会由javadoc和类似工具记录.如果类型声明使用Documented进行注释,则其注释将成为注释元素的一部分API
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE)
public @interface Documented {
}
@Inherited
a.使用该类型的注解后,只会影响类继承的接口继承,意思就是父类中使用了有该@Inherited元注解的自定义注解,那么子类也会继承下来,其他情况包括接口或者未使用时都不会继承(这一点在下面的源码中也解释的很清楚了)
package java.lang.annotation;
/**
* Indicates that an annotation type is automatically inherited. If
* an Inherited meta-annotation is present on an annotation type
* declaration, and the user queries the annotation type on a class
* declaration, and the class declaration has no annotation for this type,
* then the class's superclass will automatically be queried for the
* annotation type. This process will be repeated until an annotation for this
* type is found, or the top of the class hierarchy (Object)
* is reached. If no superclass has an annotation for this type, then
* the query will indicate that the class in question has no such annotation.
*
* <p>Note that this meta-annotation type has no effect if the annotated
* type is used to annotate anything other than a class. Note also
* that this meta-annotation only causes annotations to be inherited
* from superclasses; annotations on implemented interfaces have no
* effect.
*
* @author Joshua Bloch
* @since 1.5
* @jls 9.6.3.3 @Inherited
*/
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE)
public @interface Inherited {
}
@Native和@Repeatable
前者我们基本上不会用到,被@Native注解修饰的成员变量,则表示这个变量可以被本地代码引用,常常被代码生成工具使用,我们基本不会使用,因此简单了解一下即可.
后者@Repeatable,是运行在相同的程序元素中重复注解,在需要对同一种注解多次使用时,往往需要借助@Repeatable注解
这两者网上资料也不多,小编自己也研究不深,在此不献丑了,等之后研究一番之后,在单独为其发一篇!
3.Java中内置的注解:
@Override
a). 相信大家对这个注解并不陌生,这个注解就是标注当前方法覆盖了当前父类或父接口的方法
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.SOURCE)
public @interface Override {
}
@Deprecated
a).这个注解是标注当前对象即将被移除,已经有了更好的代替方案,建议大家不要在使用.
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(value={CONSTRUCTOR, FIELD, LOCAL_VARIABLE, METHOD, PACKAGE, PARAMETER, TYPE})
public @interface Deprecated {
}
@FunctionalInterface
a).这个注解是1.8之后出来的函数式接口注释,标注当前接口是函数式接口,为了适用当前1.8中新特性,函数式编程,
b).特点:(直接看源码注释)
/**
* An informative annotation type used to indicate that an interface
* type declaration is intended to be a <i>functional interface</i> as
* defined by the Java Language Specification.
*
* Conceptually, a functional interface has exactly one abstract
* method. Since {@linkplain java.lang.reflect.Method#isDefault()
* default methods} have an implementation, they are not abstract. If
* an interface declares an abstract method overriding one of the
* public methods of {@code java.lang.Object}, that also does
* <em>not</em> count toward the interface's abstract method count
* since any implementation of the interface will have an
* implementation from {@code java.lang.Object} or elsewhere.
1.该注解只能标记在"有且仅有一个抽象方法"的接口上
2.这里隐藏了一个java规范,jdk8中的静态方法和默认方法都不算是抽象方法
3.接口默认继承Object,所以如果接口显示声明覆盖Object中的方法,那么也不算抽象方法
*
* <p>Note that instances of functional interfaces can be created with
* lambda expressions, method references, or constructor references.
*
* <p>If a type is annotated with this annotation type, compilers are
* required to generate an error message unless:
*
* <ul>
* <li> The type is an interface type and not an annotation type, enum, or class.
* <li> The annotated type satisfies the requirements of a functional interface.
* </ul>
*
* <p>However, the compiler will treat any interface meeting the
* definition of a functional interface as a functional interface
* regardless of whether or not a {@code FunctionalInterface}
* annotation is present on the interface declaration.
报错的情况:
1.必须是一个接口,而不能是注解类型,枚举和类
2.当前接口必须满足函数式接口的要求(如果满足要求后,即使不设置该注解,编译器也会把他当成是函数式接口,但是如果他不满足,但是有这个注解,那么编译器也会报错)
*
* @jls 4.3.2. The Class Object
* @jls 9.8 Functional Interfaces
* @jls 9.4.3 Interface Method Body
* @since 1.8
*/
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface FunctionalInterface {}
@SafeVarargs
a). 使用场景,当出现一个编辑器觉得会出问题,但是你自己的代码里面不会涉及到的问题时,可以用这个来避免编辑器发出警告.具体来讲就是,可变长度的方法参数的实际值是通过数组来传递的,而数组中存储的是不可具象化的泛型类,自身存在类型安全问题,因此编译器会给出相应的警告消息
b).注意事项:该注解使用必须是可变参数方法和构造器;如果是可变参数的方法,那么必须用static和final来修饰才能使用
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.CONSTRUCTOR, ElementType.METHOD})
public @interface SafeVarargs {}
@SuppressWarnings
a).此注解的作用是给编译器一条指令,告诉编译器对被批注的代码元素内部的某些警告保持静默.
@Target({TYPE, FIELD, METHOD, PARAMETER, CONSTRUCTOR, LOCAL_VARIABLE})
@Retention(RetentionPolicy.SOURCE)
public @interface SuppressWarnings {
/**
* The set of warnings that are to be suppressed by the compiler in the
* annotated element. Duplicate names are permitted. The second and
* successive occurrences of a name are ignored. The presence of
* unrecognized warning names is <i>not</i> an error: Compilers must
* ignore any warning names they do not recognize. They are, however,
* free to emit a warning if an annotation contains an unrecognized
* warning name.
*
* <p> The string {@code "unchecked"} is used to suppress
* unchecked warnings. Compiler vendors should document the
* additional warning names they support in conjunction with this
* annotation type. They are encouraged to cooperate to ensure
* that the same names work across multiple compilers.
* @return the set of warnings to be suppressed
*/
String[] value();
}
关键字 | 用途 |
all | 抑制所有警告 |
boxing | 抑制与拆/装箱相关警告 |
cast | 抑制与强制转换相关的警告 |
dep-ann | 抑制与废弃注解相关的警告 |
deprecation | 抑制与弃用相关的警告 |
fallthrough | 抑制与switch语句中丢失的中断的相关的警告 |
finally | 抑制finally块中不返回警告 |
hiding | 抑制相对于隐藏变量的局部变量的警告 |
incomlete-switch | 抑制相对于switch语句中丢失的条目相关的警告(枚举情况) |
nls | 抑制与non-nls字符串相关的警告 |
null | 抑制解析为空相关的警告 |
rawtypes | 在类参数上使用泛型时,抑制与非特定类型相关的警告 |
serial | 抑制与可序列化类缺少serialVersionUID字段相关的警告 |
restriction | 抑制使用与禁止引用相关警告 |
static-access | 抑制与不正确的静态访问相关的警告 |
unchecked | 抑制与未检查操作相关的警告 |
unqualified-field-access | 抑制与字段访问无关的警告 |
unused | 抑制与未使用代码相关的jing |
二.Annotation
Annotation接口基本上就是所有的注解的Object了
/**
* The common interface extended by all annotation types. Note that an
* interface that manually extends this one does <i>not</i> define
* an annotation type. Also note that this interface does not itself
* define an annotation type.
*
* 更多信息可以在java语言规范9.6节中找到
* More information about annotation types can be found in section 9.6 of
* <cite>The Java™ Language Specification</cite>.
*
* The {@link java.lang.reflect.AnnotatedElement} interface discusses
* compatibility concerns when evolving an annotation type from being
* non-repeatable to being repeatable.
*
* @author Josh Bloch
* @since 1.5
*/
public interface Annotation {
boolean equals(Object obj);
int hashCode();
//重写了Object的toString方法,
String toString();
//获取注解类型
//反射-->
Class<? extends Annotation> annotationType();
}
三.总结
总得来说,从最早接触Java语言,到真正去读源码去学习注解,才发现有很多地方是不太清晰的,但是现在依旧也很多地方很模糊,归根到底就是实际使用中,对这方面使用过少,导致很多地方含糊不清.说白了,小编还是太菜了,继续脱发,继续干吧!
月央泽,我怕变成越光泽...
以上内容,部分摘选自: