转载,https://blog.csdn.net/huangshanchun/article/details/51226846
注解类似于修饰符一样被使用,可以用于包,类构造方法,方法,成员变量,参数,局部变量。
注解离开了反射,它就变成了一个空架子。
1.认识注解
注解也被称为元数据,那什么是元数据?所谓的元数据就是用来定义数据的数据,如类的属性和方法等这些都是类的元数据。注解想当与在代码做一些特殊的标记,这些注解可以在编译,类加载,运行时候不改变原有的逻辑的情况下,被读取,并执行相应的处理。 如下下面例子中Override注解所示
- public class Test {
- /*
- 这里的Override就是一个标记,也就是我们所说的注解,它标记toString()方法就是一个覆写父类中的方法,因此我们如果
- 我们将toString()方法名字写错了,则编译器就会根据这个Override的注解标记提示出相应的错误
- */
- @Override
- public String toString()
- {
- return “”;
- }
- }
public class Test {
/*
这里的Override就是一个标记,也就是我们所说的注解,它标记toString()方法就是一个覆写父类中的方法,因此我们如果
我们将toString()方法名字写错了,则编译器就会根据这个Override的注解标记提示出相应的错误
*/
@Override
public String toString()
{
return "";
}
}
注解类似于修饰符一样被使用,可以用于包,类构造方法,方法,成员变量,参数,局部变量。
2.系统定义三个内置注解以及四种元注解
注解的的语法比较简单,除了@符号使用之外,它基本与Java的固有语法一致。Java SE5内置了三种注解,定义在Java.lang中的注解:
@Override,表示当前的方法定义覆盖超类中的方法,如果你不小心拼写错误,或者方法签名对不上覆盖的方法,编译器就会发出错误提示。
@Deprecated 表示一个类或者方法以及过时,不建议再使用。如果程序员使用了它,编译器就会发出警告的信息。
@SuppressWarnings,关闭不当的编译警告信息。
下面我给出Override的注解类,JDK中定义源代码
- @Target(ElementType.METHOD)
- @Retention(RetentionPolicy.SOURCE)
- public @interface Override {
- }
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.SOURCE)
public @interface Override {
}
四种元注解主要用来注解其它的注解
(1)@Target 表示该注解可以用于什么地方,也就是说其使用范围,
值得说明的事当属性名定义为value时候,在使用该注解的赋值的时候alue可以省略。
- @Documented
- @Retention(RetentionPolicy.RUNTIME)
- @Target(ElementType.ANNOTATION_TYPE)
- public @interface Target {
- ElementType[] value();
- }
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE)
public @interface Target {
ElementType[] value();
}
枚举ElementType 主要成员,该成员用来描述枚举
- public enum ElementType {
- /** Class, interface (including annotation type), or enum declaration */
- TYPE,
- /** Field declaration (includes enum constants) */
- FIELD,
- /** Method declaration */
- METHOD,
- /** Parameter declaration */
- PARAMETER,
- /** Constructor declaration */
- CONSTRUCTOR,
- /** Local variable declaration */
- LOCAL_VARIABLE,
- /** Annotation type declaration */
- ANNOTATION_TYPE,
- /** Package declaration */
- PACKAGE
- }
public enum ElementType {
/** Class, interface (including annotation type), or enum declaration */
TYPE,
/** Field declaration (includes enum constants) */
FIELD,
/** Method declaration */
METHOD,
/** Parameter declaration */
PARAMETER,
/** Constructor declaration */
CONSTRUCTOR,
/** Local variable declaration */
LOCAL_VARIABLE,
/** Annotation type declaration */
ANNOTATION_TYPE,
/** Package declaration */
PACKAGE
}
@Retention 表示需要在什么级别上保存注解信息,SOURCE 注解将会编译器丢弃,也就是说其只在编译阶段起作用,如何Override只是在编译阶段起作用
CLASS 表示注解在class文件中可用,但在JVM中会丢弃。RUNTIME表示在运行时候注解依然可用。
- @Documented
- @Retention(RetentionPolicy.RUNTIME)
- @Target(ElementType.ANNOTATION_TYPE)
- public @interface Retention {
- RetentionPolicy value();
- }
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE)
public @interface Retention {
RetentionPolicy value();
}
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,
- /**
- * 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
- }
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,
/**
* 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 注解表示的是文档化,可以生成doc文档的时候添加的注解,该注解是一个标记。
@Inherited 注解表示一个注解是否允许被其自己继承下来
3.自定义注解
注解的应用需要三个基本步骤:
(1).编写注解
(2).在类上应用注解
(3).对应用类注解类进行反射操作的类,因为只有这样才能让注解起作用
自定义的注解的语法如下:
访问控制权限 @interface 注解名{}
下面给出一个注解实例
- package com.ahu.annotation.test.demo;
- import java.lang.annotation.ElementType;
- import java.lang.annotation.Retention;
- import java.lang.annotation.RetentionPolicy;
- import java.lang.annotation.Target;
- /*
- *自定义注解
- */
- @Target(ElementType.TYPE)
- @Retention(RetentionPolicy.RUNTIME)
- public @interface MyAnnotation {
- public String name();//注解的属性,类似于方法的定义
- public String info() default “student”;
- public String[] like();//爱好
- public EnumSex sex();//性别
- }
package com.ahu.annotation.test.demo;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/*
*自定义注解
*/
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface MyAnnotation {
public String name();//注解的属性,类似于方法的定义
public String info() default "student";
public String[] like();//爱好
public EnumSex sex();//性别
}
在User类上使用注解
- package com.ahu.annotation.test.demo;
package com.ahu.annotation.test.demo;
- /*使用自定义注解需要给相应的属性赋值,如何注解在定义的时候相应的属性已经给出了相应的缺省值,可以不用赋值,如info这个属性
- * like 数组赋值
- * sex 是枚举类型的数据赋值
- */
- @MyAnnotation(name=“hsc”,like={“running”,“watch tv”},sex=EnumSex.MALE)
- public class User {
- private String name;
- public String getName() {
- return name;
- }
- public void setName(String name) {
- this.name = name;
- }
- }
/*使用自定义注解需要给相应的属性赋值,如何注解在定义的时候相应的属性已经给出了相应的缺省值,可以不用赋值,如info这个属性
* like 数组赋值
* sex 是枚举类型的数据赋值
*/
@MyAnnotation(name="hsc",like={"running","watch tv"},sex=EnumSex.MALE)
public class User {
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
- package com.ahu.annotation.test.demo;
- public enum EnumSex {
- MALE,FEMALE
- }
package com.ahu.annotation.test.demo;
public enum EnumSex {
MALE,FEMALE
}
主函数入口测试类
- package com.ahu.annotation.test.demo;
- import java.lang.annotation.Annotation;
- public class Test {
- public static void main(String []args)
- {
- try {
- Class<?> c=Class.forName(”com.ahu.annotation.test.demo.User”);
- //获取类中标记中的所有类的标记 ,如何在类中标记可以class直接获取注解
- //如果在方法中标记可以通过获取方法拿到注解
- Annotation[] annotations=c.getAnnotations();
- for(Annotation a:annotations){
- //判断是否是自己所指定的注解
- if(c.isAnnotationPresent(MyAnnotation.class)){
- MyAnnotation my=(MyAnnotation)a; //强制转换
- System.out.println(my.name()); //输出注解内容
- System.out.println(my.info());
- }
- }
- } catch (ClassNotFoundException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- }
- }
- }
package com.ahu.annotation.test.demo;
import java.lang.annotation.Annotation;
public class Test {
public static void main(String []args)
{
try {
Class<?> c=Class.forName("com.ahu.annotation.test.demo.User");
//获取类中标记中的所有类的标记 ,如何在类中标记可以class直接获取注解
//如果在方法中标记可以通过获取方法拿到注解
Annotation[] annotations=c.getAnnotations();
for(Annotation a:annotations){
//判断是否是自己所指定的注解
if(c.isAnnotationPresent(MyAnnotation.class)){
MyAnnotation my=(MyAnnotation)a; //强制转换
System.out.println(my.name()); //输出注解内容
System.out.println(my.info());
}
}
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
注解离开了反射,它就变成了一个空架子。