说到注解,那么我们先看一下之前遇到的东西 @Override。 子类继承父类,或者实现一个接口,要重写或者实现的方法,都有一个@Override。那么其中的@Override就是注解用法,作用是对方法注解。
package java.lang;
import java.lang.annotation.*;
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.SOURCE)
public @interface Override {
}
这就是Override注解的方法说明。那么里面还有@Target 、@Retention 。这又是什么呢。这是Java定义的元注解。
元注解:
1、 @Target:
package java.lang.annotation;
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE)
public @interface Target {
ElementType[] value();
}
Target注解在使用时要传入一个ElementTeype数组参数。 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
}
打开源码就清楚多了,英语不好的,可以用谷歌翻译翻译。
2、@Retention
package java.lang.annotation;
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE)
public @interface Retention {
RetentionPolicy value();
}
Retention使用只需传入一个RetenionPolicy参数,来看看RetentionPolicy
package java.lang.annotation;
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
}
三个值,表示了注解在三个阶段的状态。SOURCE 是直接在源文件中被丢弃了。ClASS 在类文件中记录了,不保留到机器运行时。默认状态。RUNTIME 一看就是运行时状态。 3、@Documented
在Retention的声明中看到了这个了吧,
package java.lang.annotation;
/**
* Indicates that annotations with a type are to be documented by javadoc
* and similar tools by default. This type should be used to annotate the
* declarations of types whose annotations affect the use of annotated
* elements by their clients. If a type declaration is annotated with
* Documented, its annotations become part of the public API
* of the annotated elements.
*
* @author Joshua Bloch
* @since 1.5
*/@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE)
public @interface Documented {
}
指示某一类型的注释将通过javadoc中进行记录,默认情况下类似的工具。这种类型应该用于注释类型的注释影响使用注解的声明他们的客户的元素。如果一个类型声明都被注解记载,它的注解成为公共API的一部分注释的元素。这是谷歌翻译的结果,弄的好麻烦。这样理解:被Documented注解了的注解的说明,文档化之后, 此注解注释的元素的说明会携带此注解的说明。
4、@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
*/
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE)
public @interface Inherited {
}
注释类型被自动继承。
元注解,一般用于注释注解。
除了Override还有一些注解:比如@Deprecated 过时方法、@SuppressWarnings抑制警告等。
自定义注解
依然以之前的Gun类为例子;
对象初始化使用、配置:
注解Inite:
package com.test;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface Inite {
String name() default "手枪";
int bullet() default 10;
String address() default "德国";
}
Retention 表明运行时,Target表明,是属性注解。
其中 String name() default "手枪";这些元素,必须是基本类型数据或者String类型数据。
看我们的处理类:
package com.test;
import java.lang.reflect.Field;
public class ClassInite {
public static void inite( String className){
Class<?> aClass=null;
try {
aClass = Class.forName(className);
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
Field[] declaredFields = aClass.getDeclaredFields();
for (int i=0;i<declaredFields.length;i++)
{
Field field=declaredFields[i];
if (field.isAnnotationPresent(Inite.class))
{
Inite annotation = field.getAnnotation(Inite.class);
field.setAccessible(true);
field.setAccessible(true);
Gun gun=new Gun();
gun.setName(annotation.name());
gun.setBullet(annotation.bullet());
gun.setAddress(annotation.address());
try {
field.set(aClass, gun);
field.getName();
} catch (IllegalArgumentException | IllegalAccessException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
} 处理类就是把这些注解 的参数作为Gun类初始化的参数,初始化Gun.
测试类:
public class test {
@Inite
private static Gun gun1;
@Inite(name="加特林",bullet=100,address="意大利")
private static Gun gun2;
public static void main(String[] args) {
ClassInite.inite("test");
System.out.println(gun1+","+gun2);
}}
输出:
{手枪,10,德国},{加特林,100,意大利}
是不是初始化变的很方便了?上一篇反射中提到了xml配置文件转化对象,如果和那个相结合,注解类传入的参数为id,那么在注解处理类中根据id或者不需要传入注解数据,生成xml中配置的对象进行初始化。那么对于复杂的类,也就很容易了。解决了在处理类去固定new一个确定的对象的弊端。用这个注解的方式把XML配置的对象赋值到代码中对象里。
在Spring 中@Autowired就是这个基础原理,进行把Beans中的对象装配进去的,Spring更复杂。
上一边还提到了ORM,对于数据库表映射到对象。利用注解也可以初始化数据库的数据。比如初始化个人信息等。还有关于其它初始化对象的。是不是感觉到了注解的强大?
注解必须和反射一起使用,才能运用好注解。
也可以:
package com.test;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.FIELD,ElementType.METHOD,ElementType.TYPE})
public @interface note {
}Target 域为:属性、方法、类型。不添加注解内容。