Java注解
本文主要讲一下@Target,@Retention,@Constraint,@Documented:
- 四种注解简介
- Java8新增ElementType.TYPE_USE,ElementType.TYPE_PARAMETER用法
@Target
注解作用的范围
- @Target(ElementType.TYPE) //类,接口(包括注解),枚举
- @Target(ElementType.FIELD) //字段(包括枚举常量)
- @Target(ElementType.METHOD) //方法
- @Target(ElementType.PARAMETER) //参数
- @Target(ElementType.CONSTRUCTOR) //构造函数
- @Target(ElementType.LOCAL_VARIABLE)//局部变量
- @Target(ElementType.ANNOTATION_TYPE)//注解
- @Target(ElementType.PACKAGE) //包
- @Target(ElementType.TYPE_USE) //类型
- @Target(ElementType.TYPE_PARAMETER) //类型
- 查看源码,一目了然
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
*/
TYPE_USE
}
@Retention
表示注解可以保存的时间
- @Retention(RetentionPolicy.SOURCE) //注解保留在源码阶段,被编译器丢弃
- @Retention(RetentionPolicy.CLASS) // 注解被编译器保存在字节码文件中,在运行时丢弃,默认的保留行为
- @Retention(RetentionPolicy.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
}
@Constraint
这个是在validation-api-1.1.0.Final.jar包里面的类,如果你要写自定义的校验类,可以引入这个jar包,并且在自定义的校验类里面写你的相关校验,举例如下:
- 在某接口的入参引入了自定义的注解(其他注解去掉了):
/**投资金额**/
@BigDecimalRange( minPrecision = 0, maxPrecision = 11, scale =2)
private BigDecimal amount;
- 自定义的注解BigDecimalRange
@Target({METHOD, FIELD, ANNOTATION_TYPE})
@Retention(RUNTIME)
@Constraint(validatedBy = BigDecimalValidator.class)
@Documented
public @interface BigDecimalRange
{
public Class<?>[] groups() default {};
public Class<? extends Payload>[] payload() default {};
long minPrecision() default Long.MIN_VALUE;
long maxPrecision() default Long.MAX_VALUE;
int scale() default 0;
}
- Constraint类源码
@Documented
@Target({ ANNOTATION_TYPE })
@Retention(RUNTIME)
public @interface Constraint {
/**
* {@link ConstraintValidator} classes must reference distinct target types
* for a given {@link ValidationTarget}
* If two {@code ConstraintValidator}s refer to the same type,
* an exception will occur.
* <p/>
* At most one {@code ConstraintValidator} targeting the array of parameters of
* methods or constructors (aka cross-parameter) is accepted. If two or more
* are present, an exception will occur.
*
* @return array of (@code ConstraintValidator} classes implementing the constraint
*/
Class<? extends ConstraintValidator<?, ?>>[] validatedBy();
}
- 在自定义的注解里的用法如下:
@Constraint(validatedBy = BigDecimalValidator.class),BigDecimalValidator校验类里面的内容可以自己去写,如对amount范围的校验,最多几位,最少几位,以及小数点后的位数等等
@Documented
说明该注解将被包含在javadoc中
Java8新增TYPE_USE和TYPE_PARAMETER用法
package annotation;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
//ElementType.TYPE_USE是对类型的注解,如下面的泛型,String类型
//ElementType.LOCAL_VARIABLE对局部变量的注解
//ElementType.FIELD字段、枚举的常量
public class TestTypeParam <@TestAnnotation T>{
List<@TestAnnotation Map<String, String>> l1 = new ArrayList<Map<String, String>>();
//ElementType.TYPE_USE 对String类型的注解,注意区别下面的test1
@TestAnnotation String test;
//ElementType.FIELD对test1的注解
@TestAnnotation java.lang.String test1;
public String test1(){
//ElementType.LOCAL_VARIABLE 对test2的注解
@TestAnnotation java.lang.String test2 = "hh";
return test2;
}
}
反射机制读注解的值
- 自定义的注解TestAnnotation
package annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target({ElementType.METHOD, ElementType.TYPE_USE, ElementType.LOCAL_VARIABLE, ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
public @interface TestAnnotation {
public String value() default "{haha,henhao}";
}
- 用到注解的接口
package interfabstr;
import annotation.TestAnnotation;
public interface TestInterface {
public static final String STR = "abc";
String str = "";
//public static String a; 接口里的变量都是final的,必须初始化
@TestAnnotation(value=STR)
public abstract int insert1();
@TestAnnotation(value=STR)
public String getString();
@TestAnnotation(value=STR)
public void add1();
}
- 测试类
package interfabstr;
import java.lang.reflect.Method;
import annotation.TestAnnotation;
public class TestMain {
public static void main(String[] args){
Class<TestInterface> ti = TestInterface.class;
Method[] mts = ti.getMethods();
for(Method mt : mts){
TestAnnotation ta = mt.getAnnotation(TestAnnotation.class);
String s = ta.value();
System.out.println("s: " + s);
}
}
}
程序运行结果:
s: abc
s: abc
s: abc
参考:
[1] http://ifeve.com/java-annotation/
[2] http://www.cnblogs.com/Gordon-YangYiBao/archive/2012/08/07/2626340.html