文章目录
1.概念
是一种特殊标记,出现在jdk1.5后。类,方法,变量,参数和包都可以被标注。跟注释的区别就是注释是给程序员看的,而注解只给程序看的。
2.java 内置的注解
1. @Override
检查该方法是否是重写方法。如果发现其父类,或者是引用的接口中并没有该方法时,会报编译错误。
2. @Deprecated
标记过时方法、类。如果使用该方法,会报编译警告。
3. @SuppressWarnings
抑制编译器警告
例如
@SuppressWarnings({ "rawtypes", "unused" })
List list1 = new ArrayList();
在实例化ArrayList 时没有指定泛型,因此使用 @SuppressWarnings 抑制编译器警告
@SuppressWarnings 的常用参数:
参数 | 含义 |
---|---|
deprecation | 使用了不赞成使用的类或方法时的警告(使用@Deprecated使得编译器产生的警告) |
unchecked | 执行了未检查的转换时的警告,例如当使用集合时没有用泛型 (Generics) 来指定集合保存的类型; 关闭编译器警告 |
fallthrough | 当 Switch 程序块直接通往下一种情况而没有 Break 时的警告 |
path | 在类路径、源文件路径等中有不存在的路径时的警告 |
serial | 当在可序列化的类上缺少 serialVersionUID 定义时的警告 |
finally | 任何 finally 子句不能正常完成时的警告 |
rawtypes | 泛型类型未指明 |
unused | 引用定义了,但是没有被使用 |
all | 关于以上所有情况的警告 |
4. @SafeVarargs
- Java 7 开始支持,忽略任何使用参数为泛型变量的方法或构造函数调用产生的警告。
5. @FunctionalInterface
- Java 8 开始支持,标识一个匿名函数或函数式接口。
3.元注解
元注解就是作用在注解上的注解
1.@Retention
指明注解的生命周期,标识这个注解怎么保存,是只在源代码中,还是编入class文件中,或者是在运行时可以通过反射访问。
成员变量Value指定值 | 含义 |
---|---|
RetentionPolicy.SOURCE | 只存在代码中,会被编译器抛弃 |
RetentionPolicy.CLASS | 默认的保留策略,注解会在class字节码文件中存在,但运行时无法获得 |
RetentionPolicy.RUNTIME | 注解会在class字节码文件中存在,在运行时可以通过反射获取到 |
2.@Documented
标记这些注解是否包含在用户文档中。
注意:设置 @Documented 注解的 @Retention 必须为 RUNTIME
3.@Target
表示我们的注解作用的范围
例如
@Target({TYPE, FIELD, METHOD, PARAMETER, CONSTRUCTOR, LOCAL_VARIABLE})
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();
}
public enum ElementType {
/** Class, interface (including annotation type), or enum declaration */
//作用接口、类、枚举、注解
TYPE,
/** Field declaration (includes enum constants) */
//作用属性
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
*/
//作用于类型使用.可以用于标注任意类型除了 class
TYPE_USE
}
4.@Inherited
一个被 @Inherited 注解了的注解修饰了一个父类,如果他的子类没有被其他注解修饰,则它的子类也继承了父类的注解。也就是使得注解具有继承性。
5.@Repeatable
可重复注解。被这个元注解修饰的注解可以同时作用一个对象多次,但是每次作用注解又可以代表不同的含义。
@Target({TYPE, FIELD, METHOD, PARAMETER, CONSTRUCTOR, LOCAL_VARIABLE})
@Retention(RetentionPolicy.RUNTIME)
public @interface myannotattions {
myAnnotation[] value();
}
@Repeatable(myannotattions.class)
@Target({TYPE, FIELD, METHOD, PARAMETER, CONSTRUCTOR, LOCAL_VARIABLE})
@Retention(RetentionPolicy.RUNTIME)
public @interface myAnnotation {
String[] value();
}
@com.annotation.myAnnotation("ls1")
@com.annotation.myAnnotation("ls")
public class collectionTest01 {
4.自定义注解(配合反射)
可以先来看一下 @SuppressWarnings 中的内容,参照 @SuppressWarnings 来自定义注解
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();
}
只有一个 String[] value();
这是一个成员变量。因为在注解中的成员变量是以无参方法的形式来申明。而这个String[] 为该变量的类型,可以给该成员赋一个默认值
public @interface myAnnotation {
String[] value() default "ls";
}
如果没有默认值时,在使用注解的时候要赋值
@com.annotation.myAnnotation("ls")
public class collectionTest01 {
}
注解中定义属性时它的类型必须是 8 种基本数据类型外加 类、接口、注解及它们的一维数组。
value 是注解中的一个特殊属性,如果注解中只有它这一个属性时,我们在使用注解的时候可以省略value=部分,直接写成myAnnotation(“ls”),如果不是,则要写成 @myAnnotation(ans =“ls1”)
public @interface myAnnotation {
String[] ans();
}
5.注解的简单使用
上面我们将的都是注解的内容,接下来讨论注解的作用。
官方解释:
注解是一系列元数据,它提供数据用来解释程序代码,但是注解并非是所解释的代码本身的一部分。注解对于代码的运行效果没有直接影响。
可以把注解想象成一个标签,他是用来解释代码的。对于java内置的注解,我们可以直接在类、方法、属性上修饰,而对于我们自定义注解,可以通过反射提取注解的信息,根据注解信息,告诉程序如何去运行类
在框架中,注解的使用非常多,比如spring中的@Component 就是告诉spring需要把该类当成bean放入容器中
注解内容的提取
@Target({TYPE, FIELD, METHOD, PARAMETER, CONSTRUCTOR, LOCAL_VARIABLE})
@Retention(RetentionPolicy.RUNTIME)
public @interface myAnnotation {
String[] ans();
int age() default 10;
}
@myAnnotation(ans = "example")
public class example {
String value;
@myAnnotation(ans = "test1,test2",age = 20)
public int test(){
return 0;
}
}
public class anno {
public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException {
//通过反射获取example类的Class对象
Class<?> aClass = Class.forName("com.annotation.example");
System.out.println(aClass);
//获取类上的注解信息
myAnnotation myannotation = aClass.getAnnotation(myAnnotation.class);
System.out.println(Arrays.toString(myannotation.ans()) + myannotation.age());
//获取方法上的注解信息
Method method1 = aClass.getMethod("test");
//判断该方法上是否右myAnnotation注解
if(method1.isAnnotationPresent(myAnnotation.class)){
System.out.println(Arrays.toString(myannotation.ans()) + myannotation.age());
}
}
}
注解使用最终是需要依靠特定的程序去读取注解,得到注解的一些信息,根据注解的信息来确定接下来该做什么。