自定义注解的解释1
自定义Annotation
注解应用需要三个步骤:
1)、编写注解
2)、在类上应用注解
3)、对应用了注解的类进行反射操作的类
自定义Annotation的语法:
访问控制权限 @interface Annotation名称{}
举例:
public @interface MyAnnotation{}
1、在Annotation中定义变量{变量名称后面注意要用小括号()}
public @interface MyAnnotation{
public String name();
public String info();
}
定义变量后,在调用此Annotation时必须设置变量值
@MyAnnotation(name="vince",info="hello")
public class Demo{}
通过Default指定变量默认值,有了默认值在使用注解时就可以不设置
public @interface MyAnnotation{
public String name() default "vince"
public String info() default "hello"
}
2、在Annotation中定义一个数组
public @interface MyAnnotation{
public String[] name();
}
在使用注解时需要指定数组的值
@MyAnnotation(name={"jack","vince"})
public class Demo{}
3、使用枚举限制变量取值范围
public enum Color{
RED,GREEN,YELLOE
}
public @interface MyAnnotation{
public Color color();
}
4、Retention和RetentionPolicy
注解的作用范围通过@Retention指定,而Retention指定的范围由RetentionPolicy决定,RetentionPolicy指定了三种范围:
RetentionPolicy.SOURCE //在java源程序中存在
RetentionPolicy.CLASS //在java生成的class中存在
RetentionPolicy.RUNTIME //在java运行的时候存在
举例:
@Rentention(RetentionPolicy.RUNTIME)
public @interface MyAnnotation{
public String name();
}
自定义注解的解释2
5、反射使自定义注解生效
一个Annotation注解整整起作用,必须结合反射机制,在反射中提供了以下的操作方法:
public boolean isAnnotationPresent() //判断是否是指定的Annotation
public Annotation getAnnotation() //得到指定的Annotation
public Annotation[] getAnnotations() //得到全部的Annotation
6、
@Documented 注解表示以上的注释会生成文档用
7、
@Target注解表示的是一个Annotation的使用范围,例如:之前定义的MyAnnotation可以在任意的位置上使用
ElementType.TYPE //只能在类或接口或枚举上使用
ElementType.FIELD //在成员变量中使用
ElementType.METHOD //在方法中使用
ElementType.PARAMETER //在参数中使用
ElementType.CONSTRUCTOR //在构造中使用
ElementType.LOCAL_VARIABLE //在局部变量上使用
ElementType.ANNOTATION //只能在Annotation中使用
ElementType.PACKAGE //只能在包中使用
8、
@Inherited注解:表示一个Annotation是否允许被其子类继承下来
自定义注解MyAnnotation.java
import java.lang.annotation.*;
//自定义注解
@Documented //该注解表示:上方的注释会生成文档用
@Retention(RetentionPolicy.RUNTIME) //该注解表示:以下自定义的注解作用范围是在运行的时期
@Target({ElementType.TYPE,ElementType.METHOD})
@Inherited //该注解表示:可以被其子类继承
public @interface MyAnnotation {
//定义自定义注解的变量
public String name();
public int age() default 2; //给变量设置默认值
public String[] like(); //定义一个数组变量
public Color color(); //定义一个枚举类型的变量
}
应用自定义注解
@MyAnnotation(name="vince",like={"鲫鱼","金鱼"},color=Color.BLACK) //应用自定义注解
public class Cat {
private String name;
private int age;
private Color color;
private String[] like;
public Cat(){ }
public Cat(String name, int age, Color color, String[] like) {
this.name = name;
this.age = age;
this.color = color;
this.like = like;
}
public Color getColor() {
return color;
}
public void setColor(Color color) {
this.color = color;
}
public String[] getLike() {
return like;
}
public void setLike(String[] like) {
this.like = like;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override //该注解表示:用于验证方法是否覆盖父类的方法
public String toString() {
return "Cat{" +
"name='" + name + '\'' +
", age=" + age +
", color=" + color +
", like=" + Arrays.toString(like) +
'}';
}
@Deprecated //该注解表示:该方法已过时不建议再使用
public String printInfo(){
return "Cat{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
反射注解的应用
import org.junit.Test;
import java.lang.reflect.Method;
public class AnnotationDemo {
@Test
public void test() {
Cat cat = new Cat("bin", 3,Color.YELLOW, new String[]{"鲫鱼", "金鱼"});
cat.printInfo(); //这里划横线就表示该方法在源类中已被注解为过时的方法,但是强制调用也可以
}
@Test
public void test2(){
//源目标类的反射都到Class类
Class<Cat> catClass = Cat.class;
//获取类上应用的指定的注解
MyAnnotation annotation = catClass.getAnnotation(MyAnnotation.class);
//获取注解上的指定的变量值
int age = annotation.age();
Color color = annotation.color();
String name = annotation.name();
String[] like = annotation.like();
try {
//反射的newInstance方法获取原目标类的对象
Cat cat = catClass.newInstance();
//将注解里的变量值设置给类的属性
cat.setAge(age);
cat.setName(name);
cat.setColor(color);
cat.setLike(like);
System.out.println(cat.toString());
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
@Test
public void test3(){
try {
Class<?> aClass = Class.forName("com.vince.Annotation.Cat");
//反射找到指定的源目标类的方法setName()
Method sn = aClass.getMethod("setName",String.class);
if(sn.isAnnotationPresent(MyAnnotation.class)){ //判断源目标类的setName()方法是否是使用了指定的MyAnnotation
MyAnnotation annotation = (MyAnnotation)sn.getAnnotation(MyAnnotation.class);
String name = annotation.name();
Cat cat = (Cat)aClass.newInstance();
cat.setName(name);
System.out.println(name);
}
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
}
}
}