Annotation-注解
Annotation-注解:(注释类型)
- 1、注解Annotation是一种引用数据类型。编译之后也是生成xxx.class文件。
- 2、自定义注解: public @interface 注解类型名{ }
Annotation-JDK内置注解:元注解:用来标注“注解类型”的“注解”,称为元注解。
常见的元注解: @ Retention
- @Target注解:是元注解,Target注解用来标注“被标注的注解”可以出现在哪些位置上。
- 出现在"方法": @Target(ElementType.METHOD)
- 出现在"属性": @Target(ElementType.FIELD)
- 出现在"局部变量": @Target(ElementType.LOCAL_VARIABLE)
- 出现在"包": @Target(ElementType.PACKAGE)
- 出现在"类": @Target(ElementType.TYPE)
- 允许该注解可以标注类、方法 :@Target( {ElementType.TYPE, ElementType.METHOD} )
常见的元注解:
@ Retention :source源文件;class文件; runtime保存class文件,可被反射机制读取
- Retention注解:是元注解,Retention注解用来标注“被标注的注解”最终保存在哪里。
- 保留在java源文件中: @Retention(RetentionPolicy.SOURCE)
- 保存在class文件中: @Retention(RetentionPolicy.CLASS)
- 保存在class文件中,可被反射机制读取@Retention(RetentionPolicy.RUNTIME)
Annotation-JDK内置注解:java.lang包下的注释类型:
- @Deprecated 用 @Deprecated 注释的程序元素,过时的方法;不鼓励使用这样的元素,因为它很危险或存在更好的选择。
- @Override 表示一个方法声明打算重写超类中的另一个方法声明。
- @SuppressWarnings-忽略注解中声明的警告
//JDK中源代码 public @interface Override { }
public class AnnotationTest02 { //@Override 报错 private int no; //属性 @Override // @Override这个注解只能注解方法。 public String toString() { //方法 return "toString"; } }
当注解中有属性时:
public @interface MyAnnotation { /** * 通常在注解当中可以定义属性,以下这个是MyAnnotation的name属性。 * 看着像1个方法,但实际上我们称之为属性name。 * @return */ String name(); //颜色属性 String color(); //年龄属性 int age() default 25; //属性指定默认值 }
public class MyAnnotationTest { // 报错的原因:如果一个注解当中有属性,那么必须给属性赋值。(除非该属性使用default指定了默认值。) /*@MyAnnotation public void doSome(){ }*/ //指定name属性的值就好了。 //@MyAnnotation(属性名=属性值,属性名=属性值,属性名=属性值) @MyAnnotation(name = "zhangsan", color = "红色") public void doSome(){ } }
注解中的属性类型:
public @interface MyAnnotation { /* 注解当中的属性可以是哪一种类型? 属性的类型可以是: byte short int long float double boolean char String Class 枚举类型 以及以上每一种的数组形式。 */ int value1(); String value2(); int[] value3(); String[] value4(); Season value5(); Season[] value6(); //枚举:一年四季 Class parameterType(); Class[] parameterTypes(); }
@Targe 联合 @Retention
允许反射机制获取类中属性信息
//只允许该注解可以标注类、方法 @Target({ElementType.TYPE, ElementType.METHOD}) // 希望这个注解可以被反射 @Retention(RetentionPolicy.RUNTIME) public @interface MyAnnotation { /* value属性。 */ String value() default "北京大兴区"; }
@MyAnnotation("上海浦东区") public class MyAnnotationTest { //@MyAnnotation int i; //@MyAnnotation public MyAnnotationTest(){ } @MyAnnotation public void doSome(){ //@MyAnnotation int i; } }
public class ReflectAnnotationTest { public static void main(String[] args) throws Exception{ // 获取这个类 Class c = Class.forName("com.bjpowernode.java.annotation5.MyAnnotationTest"); // 判断类上面是否有@MyAnnotation //System.out.println(c.isAnnotationPresent(MyAnnotation.class)); // true if(c.isAnnotationPresent(MyAnnotation.class)){ // 获取该注解对象 MyAnnotation myAnnotation = (MyAnnotation)c.getAnnotation(MyAnnotation.class); //System.out.println("类上面的注解对象" + myAnnotation); // @com.bjpowernode.java.annotation5.MyAnnotation() // 获取注解对象的属性怎么办?和调接口没区别。 String value = myAnnotation.value(); System.out.println(value); } // 判断String类上面是否存在这个注解 Class stringClass = Class.forName("java.lang.String"); System.out.println(stringClass.isAnnotationPresent(MyAnnotation.class)); // false } }
反射机制获取注解属性信息
@Retention(RetentionPolicy.RUNTIME) @Target(ElementType.METHOD) public @interface MyAnnotation { //username属性 String username(); //password属性 String password(); }
public class MyAnnotationTest { @MyAnnotation(username = "admin", password = "456456") public void doSome(){ } public static void main(String[] args) throws Exception{ // 获取MyAnnotationTest的doSome()方法上面的注解信息。 Class c = Class.forName("com.bjpowernode.java.annotation6.MyAnnotationTest"); // 获取doSome()方法 Method doSomeMethod = c.getDeclaredMethod("doSome"); // 判断该方法上是否存在这个注解 if(doSomeMethod.isAnnotationPresent(MyAnnotation.class)) { MyAnnotation myAnnotation = doSomeMethod.getAnnotation(MyAnnotation.class); System.out.println(myAnnotation.username()); System.out.println(myAnnotation.password()); } } }
注解在开发中有 需求:
- 假设有这样一个注解,叫做:@Id 这个注解只能出现在类上面,当这个类上有这个注解的时候,
- 要求这个类中必须有一个int类型的id属性。如果没有这个属性
- 就报异常。如果有这个属性则正常执行!
//这个注解@Id用来标注类,被标注的类中必须有一个int类型的id属性,没有就报异常。 // 表示这个注解只能出现在类上面 @Target(ElementType.TYPE) // 该注解可以被反射机制读取到 @Retention(RetentionPolicy.RUNTIME) public @interface MustHasIdPropertyAnnotation { }
@MustHasIdPropertyAnnotation public class User { int id; String name; String password; }
/* 自定义异常 继承:RuntimeException 提供无参构造,和有参构造 */ public class HasNotIdPropertyException extends RuntimeException { public HasNotIdPropertyException(){ } public HasNotIdPropertyException(String s){ super(s); } }
public class Test { public static void main(String[] args) throws Exception{ // 获取类 Class userClass = Class.forName("com.bjpowernode.java.annotation7.User"); // 判断类上是否存在Id注解 if(userClass.isAnnotationPresent(MustHasIdPropertyAnnotation.class)){ // 当一个类上面有@MustHasIdPropertyAnnotation注解的时候,要求类中必须存在int类型的id属性 // 如果没有int类型的id属性则报异常。 // 获取类的属性 Field[] fields = userClass.getDeclaredFields(); boolean isOk = false; // 给一个默认的标记 for(Field field : fields){ if("id".equals(field.getName()) && "int".equals(field.getType().getSimpleName())){ // 表示这个类是合法的类。有@Id注解,则这个类中必须有int类型的id isOk = true; // 表示合法 break; } } // 判断是否合法 if(!isOk){ throw new HasNotIdPropertyException("被@MustHasIdPropertyAnnotation注解标注的类中必须要有一个int类型的id属性!"); } } } }