1. 注解定义
注解是一种特殊的注释,是一种引用数据类型,可以注解Java中所有数据类型,可以出现在任何位置。
2. 注解的语法格式
public @interface OtherAnnotation{ }
使用@interface定义注解,名字是OtherAnnotation,意味着它实现了java.lang.annotaion.Annotaion接口。Annotation接口的实现细节都是由编译器完成的,通过@interface定义注解后,该注解不能继承其他的注解或接口。
@OtherAnnotation public @interface MyAnnotation{ }
定义注解后,可以使用@OtherAnnotation来使用这个注解,注解也可以“注解”注解。
package com.lewang.annotaion; @MyAnnotaion public class AnnotaionTest01{ @Deprecated public String name; @MyAnnotaion private int no; @MyAnnotaion public AnnotationTest01{ } @MyAnnotaion public static void m1(){ } @MyAnnotaion public void m2(){ } } @MyAnnotaion interface MyInterface{ } @MyAnnotaion enum Season{ SPRING,SUMMER,WINTER }
注解是一种引用数据类型,几乎可以注解java中所有数据类型。
3. 自定义注解
自定义注解如果由属性,那么注解需要赋值,默认类型可以不用赋值
public @interface MyAnnotation01{ //name属性 String name(); //email属性 String email(); //age属性 int age() default 23; }
public class Annotation02{ @MyAnnotation(name="james",email="james23@google.com") public void m1(){ } }
自定义注解属性值是value时,value可以省略
public @interface MyAnnotation02{ //属性是value String value(); }
public class AnnotationTest02{ @MyAnnotation02(value = "a") public void m1(){} @MyAnnotation02("b") public void m2(){} }
注解属性可以是枚举类型;当属性是字符串时,只有一个字符串时可以不用带大括号
public enum Season{ SRPING,WINTER,SUMMER }
public @interface MyAnnotation03{ int age(); String[] name(); Season[] value(); //属性可以时枚举类型 }
public class AnnotationTest03{ @MyAnnotation03(age=37,name={"james","kobe"},value=Season.WINTER) public void m1(){} @MyAnnotation03(age=37,name="kobe",value=Season.SPRING) //当字符串属性时只有一个字符串,可以不用带大括号 public void m2(){} }
4. 元注解
用来标注“注解类型”的注解,通常用在注解的定义上。
@Target({ElementType.METHOD,ElementType.TYPE}) @Retention(RetentionPolicy.RUNTIME) public @interface MyAnnotation{ String value(); }
Java中常见的元注解
@Target:用来标注“被标注的注解 ”可以出现在哪些位置上
@Target(ElementType.METHOD,ElementType.TYPE):表示“被标注的注解”可以出现在方法上,可以出现在类上,不能出现其他类型上;
@Retention:用来标注“被标注的注解”最终保存在哪里
@Retention(RetentionPolicy.SOURCE):表示该注解只被保存在java源文件中;
@Retention(RetentionPolicy.CLASS):表示该注解被保存在class文件中;
@Retention(RetentionPolicy.RUNTIEM):表示该注解被保存在class文件中,并且该注解可以被反射机制读取;
@Documented:表示该注解可以出现在javadoc中
@Deprecated:该注解标注的内容过时,不再推荐使用
@Override:只能标注方法,表示该方法覆盖父类中的方法
示例1:元注解和反射(@Target,@Retention)
/* 元注解只能注解类和方法,不能注解其他类型,可以保存在class文件中,可以被反射 */ @Target({ElementType.METHOD,ElementType.TYPE}) @Retention(RetentionPolicy.RUNTIME) public @interface MyAnnotation04{ String value(); }
@MyAnnotation04("aa") public class AnnotationTest04{ @MyAnnotation04("bb") public void m1(){} //@MyAnnotation04("dd") //错误: 注释类型不适用于该类型的声明 private int i; }
public class AnnotationTest05{ public static void main(String[] args) throws Exception{ Class annotaionClass = Class.forName("com.lewang.annotation04.AnnotationTest04"); //类AnnotationTest04是否有MyAnnotation04注解 System.out.println(annotaionClass.isAnnotationPresent(MyAnnotation04.class)); //true if(annotaionClass.isAnnotationPresent(MyAnnotation04.class)){ //获取注解对象 MyAnnotation04 myAnnotation = (MyAnnotation04)annotaionClass.getAnnotation(MyAnnotation04.class); System.out.println("类上的注解:" + myAnnotation); String annotationvalue = myAnnotation.value(); //获取注解属性 System.out.println(annotationvalue); } Class stringclass = Class.forName("java.lang.String"); System.out.println(stringclass.isAnnotationPresent(MyAnnotation04.class)); //false } }
示例2:反射获取注解属性值
@Target(ElementType.METHOD) @Retention(RetentionPolicy.RUNTIME) public @interface MyAnnotation05{ String username(); String password(); }
public class AnnotationTest06{ @MyAnnotation05(username="adm",password="123") public void m1(){} public static void main(String[] args) throws Exception{ Class annotationclass = Class.forName("com.lewang.annotation05.AnnotationTest06"); Method method = annotationclass.getDeclaredMethod("m1"); if(method.isAnnotationPresent(MyAnnotation05.class)){ MyAnnotation05 myannotation = method.getAnnotation(MyAnnotation05.class); System.out.println(myannotation.username()); System.out.println(myannotation.password()); } } }
示例3:注解的应用,创建一个注解,用这个注解注解一个类,在另一个类中反射类,判断类中是否有需要的属性
public class MyException extends Exception{ public MyException(){} public MyException(String s){super(s);} }
@Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) public @interface MyAnnotation06{ }
@MyAnnotation06 public class User{ //int id; String name; }
public class AnnotationTest07{ public static void main(String[] args) throws Exception{ Class userclass = Class.forName("com.lewang.annotaion07.User"); if(userclass.isAnnotationPresent(MyAnnotation06.class)){ Field[] fields = userclass.getDeclaredFields(); boolean flag = false; for(Field field : fields){ if("id".equals(field.getName()) && "int".equals(field.getType().getName())){ flag = true; break; } } if(!flag){ throw new MyException("被MyAnnotation06注解的类必须要有id属性"); } } } }
@Deprecated :标注表示过时的,不推荐使用的,在IDEA中调用会加一横线
@Override : 标注表示会覆盖父类中同名的方法,如果父类中没有同名的方法,则会产生编译告警
public class OverrideTest{ @Override public String toString(){ return "Override toString"; } @Override public String getString(){ // 错误: 方法不会覆盖或实现超类型的方法 return "getString"; } public static void main(String[] args){} }