Java注解解析
注解,也被成为元数据,为我们在代码中添加信息提供了一种形式化的方法,使我们可以在稍后某个时刻非常方便的使用这些数据。—-JAVA编程思想的注解描述。
什么是注解
在JAVA中,我们最常见的有:
123 |
@Override //当前类的某一个方法重写了父类的方法,当有这个注释但该方法不是父类的时候编译报错@Deprecated //表明这是一个废弃的方法,不提倡使用,可能后续版本去除掉该方法@SuppressWarnings //压制编译警告 |
我们看一下@Override的定义
1234 |
@Target(ElementType.METHOD)@Retention(RetentionPolicy.SOURCE)public @interface Override {} |
这样子就定义了Override这个注解。
注解就是使用一个@进行引用,他可以使用在类,方法,属性上,用于修饰。通过使用注解,我们可以做一些简化的操作,使得程序更加规范,同时也便于管理和编写。
定义注解
定义注解之前,我们需要先了解元注解。
元注解
元注解:就是用来标记自定义注解的注解,是JDK为我们提供的。比如:
1234 |
@Target@Retention@Documented //表明该注解会被javadoc包含@inherited //表明允许子类继承父类中的注解 |
其中常用的是下面的两个
- @Target 定义:
123456789101112
@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();}
他的作用是指明我们自己定义使用的对象是什么,可以看到他自己的target是ANNOTATION_TYPE,就是用来定义注解的。
我们常用是下面的type,
12345 |
ElementType.TYPE //表明注解是使用在类,接口,enum中ElementType.METHOD //表明注解是使用在方法中ElementType.FIELD//表明注解属性中ElementType.PARAMETER //表明注解是用来注解参数ElementType.CONSTRUCTOR //表明注解是使用在构造参数中 |
@Target可以同时指定多个类型,使用是
1 |
@Target({TYPE, FIELD, METHOD, PARAMETER, CONSTRUCTOR, LOCAL_VARIABLE}) |
- @Retention
用来表明注解的起作用的时期,他的定义是:12345678910
@Documented@Retention(RetentionPolicy.RUNTIME)@Target(ElementType.ANNOTATION_TYPE)public @interface Retention { /** * Returns the retention policy. * @return the retention policy */ RetentionPolicy value();}
他的值是只能一个,不能像Target指定多个,只是RetentionPolicy 类型,有:
123 |
SOURCE // 编译时期起作用,可以通过发射破坏CLASS//会被编译到被修饰的类的字节码中,但是仍然可以通过发射破坏,jvm不会加载这些注解信息,当我们没有为我们的注解指定Retention的时候默认值就是CLASSRUNTIME//在运行期起作用,会被编译到被修饰的类的字节码中,无法通过反射破坏 |
定义
例如:
123456 |
@Retention(RetentionPolicy.SOURCE)@Target({ElementType.TYPE,ElementType.FIELD})public @interface CustomAnnotations{} |
上面定义了一个名字为CustomAnnotations的注解,他是可以用来修饰类,接口,属性的,他只是存在于编译时期,不会被编译到字节码中。例如:
123456 |
@CustomAnnotationspublic class Test{ @CustomAnnotations private int a;} |
使用
本例子来源于java编程思想:
12345678 |
@Target(ElementType.METHOD)@Retention(RetentionPolicy.RUNTIME)public @interface Usecase{ public int id() default 0; public String description() default "no descriptions";} |
定义一个注解,他是用在方法中,以及是在运行时起作用,会被编译到字节码中。
使用:
12345678910111213141516 |
public class PasswordUtils{ @Usecase(id = 47,description="password must contains at least one numebic") public boolean vaildatePassword(String password){ return (password.matches("\w*\d\w*")); } @Usecase(id = 48) public String encryPassword(String password){ return new StringBuilder(password).reverse().toString(); } @Usecase(id = 49,description="new paddwords cant't equal previously use ones's") public boolean checkForNewPassword(List<String> prevPasswords,String password){ return !prevPasswords.contains(password); }} |
可以看到,我们定义了注解之后,可以选择性的使用注解的方法,使用方式是:
1 |
@Annotation(methodA=[],methodB=[]...) |
注解的方法是可选的,我们可以使用关键字default为注解的方法指定默认值,像上面那样子。
注解可以使用的数据类型有:
- java的基本类型
- String类型
- Class类型
- enum枚举类型
- Annotation类型
以及上面所有类型的数组使用注解实现注入
使用注解实现注入的很大一个好处就是不用写很多重复的代码,同时提供一套模板给外部调用者使用,规范开发和节省开发时间。