使用注解
//注释会被编译器直接忽略,
// 注解则可以被编译器打包进入class文件,因此,注解是一种用作标注的“元数据”。
//@SuppressWarnings //忽略此代码的警告
//@Override // 检测是否覆写
//定义注解时还可以配置参数:基本类型,String,枚举
class Hello {
@Check(min=0, max=100, value=55)
public int n;
@Check(value=99)
public int p;
@Check(99) // @Check(value=99)
public int x;
@Check
public int y;
}
定义注解
//@Target()
//使用@Target可以定义Annotation能够被应用于源码的哪些位置:
//
// 类或接口:ElementType.TYPE;
// 字段:ElementType.FIELD;
// 方法:ElementType.METHOD;
// 构造方法:ElementType.CONSTRUCTOR;
// 方法参数:ElementType.PARAMETER
@Target({ElementType.METHOD, ElementType.FIELD})
@interface Report
{
int type() default 0;
String level() default "info";
}
//@Retention()
//@Retention定义了Annotation的生命周期:
//
// 仅编译期:RetentionPolicy.SOURCE;
// 仅class文件:RetentionPolicy.CLASS;
// 运行期:RetentionPolicy.RUNTIME。
//如果@Retention不存在,则该Annotation默认为CLASS。
// 因为通常我们自定义的Annotation都是RUNTIME,
// 所以要加上@Retention(RetentionPolicy.RUNTIME)
@Retention(RetentionPolicy.RUNTIME)
@interface Re
{
int type() default 0;
}
//@Inherited定义子类继承父类的注解
//@Repeatable()添加多个相同的注解
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@interface Colors
{
String value() default "red";
}
@Colors("green")
class Shirt
{
}
处理注解
/*
根据@Retention的配置:
SOURCE类型的注解在编译期就被丢掉了;
CLASS类型的注解仅保存在class文件中,它们不会被加载进JVM;
RUNTIME类型的注解会被加载进JVM,并且在运行期可以被程序读取
判断某个注解是否存在于Class、Field、Method或Constructor:
Class.isAnnotationPresent(Class)
Field.isAnnotationPresent(Class)
Method.isAnnotationPresent(Class)
Constructor.isAnnotationPresent(Class)
boolean b = Person.class.isAnnotationPresent(Report.class);
System.out.println(b);//true
*/
Class cls = Person.class;
Annotation r = cls.getAnnotation(Report.class);
if(r == null)
{
System.out.println("false");
}
// 获取方法参数的注解
Method m = cls.getMethod("getName");
Annotation[][] annotations = m.getParameterAnnotations();
Annotation[] an = annotations[0];
for (Annotation anno: an)
{
if(anno instanceof Report)
{
Report r1 = (Report) anno;
}
}
}
void check(Person person) throws IllegalAccessException {
for (Field f : person.getClass().getFields())
{
Range r = f.getAnnotation(Range.class);
if (r != null)
{
Object value = f.get(person);
if(value instanceof String)
{
String s = (String) value;
int len = s.length();
if (len < r.max() && len > r.min())
{
throw new IllegalAccessException("Invalid field: " + f.getName());
}
}
}
}
}
}
/*
可以通过程序处理注解来实现相应的功能:
对JavaBean的属性值按规则进行检查;
JUnit会自动运行@Test标记的测试方法
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
@interface Range// String 字长
{
int min() default 0;
int max() default 255;
}
class Person
{
@Range(max = 10)
public String name;
public String getName(String name)
{
return "Person";
}
}
@Retention(RetentionPolicy.RUNTIME)
@interface Report
{
int type() default 0;
}