这是我参与8月更文挑战的第2天,活动详情查看:8月更文挑战
注解
注解(Annotation),也叫元数据。一种代码级别的说明。它是JDK1.5及以后版本引入的一个特性,与类、接口、枚举是在同一个层次。它可以声明在包、类、字段、方法、局部变量、方法参数等的前面,用来对这些元素进行说明,注释。(摘自百度百科)
如何声明一个注解
定义一个注解与类不同,用@interface修饰,并且修饰在"注解"之上的注解称之为元注解。
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target(ElementType.TYPE_PARAMETER)
@Retention(RetentionPolicy.CLASS)
public @interface CustonAnnotation {
String name() default "Shixf";
}
定义完成后光标放到注解名上Ctrl+U。(IDEA打开父类的接口方法快捷键)所有注解默认Annotation接口。
public interface Annotation {
boolean equals(Object obj);
int hashCode();
String toString();
Class<? extends Annotation> annotationType();
}
元注解
- 元注解: 在定义注解时,也可以使用其他的注解声明。对注解类型进行注解的注解称之为 meta-anntotain(元注解)。
- @Target: 限制可以应用注解的 Java 元素类型。目标注解指定以下元素类型之一作为其值。
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
}
对TYPE_PARAMETER特别说明下,Jdk1.8引入的可以作用于泛型上,我还没有见到在哪里有用过,对这块有研究的大佬可以@我下。
注:这个注解在上文声明过。
- @Retention:注解的保留级别
public enum RetentionPolicy {
/**
* 标记的注解仅保留在源码级别,被编译器忽略
*/
SOURCE,
/**
* 标记的注解在编译时有编译器保留,但是Java虚拟机会忽略它
*/
CLASS,
/**
* 标记的注解由JVM保留,因此运行时环境可以使用它
*/
RUNTIME
}
另外还有 @Documented 与 @Inherited 元注解,前者用于被javadoc工具提取成文档,后者表示允许子类 继承父类中定义的注解。这里不做过多解释。不解释不代表不重要。
注解的应用场景
按照 @Retention 元注解定义的注解存储方式,注解可以被在三种场景下使用
- SOURCE:作用于源码级别,可提供给IDE语法检查、APT等场景使用(在类中使用 SOURCE 级别的注解,编译之后的class中不存在) 例如Android中的@Dimension
@Documented
@Retention(SOURCE)
@Target({METHOD,PARAMETER,FIELD,LOCAL_VARIABLE,ANNOTATION_TYPE})
public @interface Dimension {
@Unit
int unit() default PX;
int DP = 0;
int PX = 1;
int SP = 2;
@IntDef({PX, DP, SP})
@Retention(SOURCE)
@interface Unit {}
}
原本我认为findViewById中@IdRes是用SOURCE级别,原来人家使用的是CLASS级别,拿个小本本记上,研究下。
- CLASS:定义为CLASS的注解,会保留在class文件中,但是会被虚拟机忽略(即无法在运行时反射获取注解)。此时完全符合此种注解的应用场景为字节码操作,如AspectJ、热修复Roubust中。
- RUNTIME:注解保留至运行期,意味着我们能够在运行期结合反射技术获取注解中的所有信息。