Java 注解(Annotation)又称 Java 标注,是 JDK5.0 引入的一种注释机制。
注解
内置注解
Java 定义了一套注解,共有 7 个,3 个在 java.lang 中,剩下 4 个在 java.lang.annotation 中。
作用代码的注解
- @Override - 检查该方法是否是重写方法。如果发现其父类,或者是引用的接口中并没有该方法时,会报编译错误。
- @Deprecated - 标记过时方法。如果使用该方法,会报编译警告。
- @SuppressWarnings - 指示编译器去忽略注解中声明的警告。
元注解
元注解是用来负责注解其他注解,Java提供了4个标准的meta-annotation提供对其他注解的类型说明,在java.lang.annotation包中
- @Target 用于描述注解的使用范围(注解可以使用在什么地方,类,方法,属性)
- @Retention 标注注解的生命周期(SOURCE<ClASS<RUNTIME)
- @Documented 标记这些注解是否包含在用户文档Java doc中。
- @Inherited 说明子类可以继承父类的该注解
// 注解能够使用在什么地方
@Target({ElementType.TYPE,ElementType.METHOD})
// 表示注解的生效范围,是编译期还是运行期或者编译后,SOURCE<ClASS<RUNTIME
@Retention(RetentionPolicy.RUNTIME)
// 表示注解是否生成在java doc中
@Documented
// 子类可以继承父类的注解
@Inherited
public @interface MyAnnotation {
}
额外注解
从 Java 7 开始,额外添加了 3 个注解:
- @SafeVarargs - Java 7 开始支持,忽略任何使用参数为泛型变量的方法或构造函数调用产生的警告。
- @FunctionalInterface - Java 8 开始支持,标识一个匿名函数或函数式接口。
- @Repeatable - Java 8 开始支持,标识某注解可以在同一个声明上使用多次。
自定义注解
语法
public @interface 注解名{}
注解元素必须要有值,通常使用0或者空字符串作为默认值
// 注解能够使用在什么地方
@Target({ElementType.TYPE,ElementType.METHOD})
// 表示注解的生效范围,是编译期还是运行期或者编译后
@Retention(RetentionPolicy.RUNTIME)
// 表示注解是否生成在java doc中
@Documented
// 子类可以继承父类的注解
@Inherited
public @interface MyAnnotation {
/** 注解的参数:参数类型+参数名() */
String name() default "";
int age() default 0;
// 默认值为-1 代表不存在,类似于indexOf(),没有返回-1
int id() default -1;
// 数组,可以传入多个值
String[] schools();
}
使用
// 注解参数没有顺序
@MyAnnotation(name = "llll",schools = {"1111","2222"},age = 15)
public class TestClazzAnnotation {
}
当注解只有一个参数的时候,建议使用value字段,因为使用时候可以直接省略
@interface MyAnnotation2{
String value();
}
@MyAnnotation2("value的属性直接省略")
public class TestClazzAnnotation {
}
反射机制(Reflection)
Java反射机制可以让程序在执行期间借助reflection API获取任何类的内部信息,并能直接操作任意对象的内部属性及方法。
优点
反射可以动态创建对象和编译
获取Class对象的方式
一个类在内存中只会有唯一一个Class对象,类被加载后的信息全部会被封装在Class对象中
三种方式
@Test
public void getClassName() throws ClassNotFoundException {
// 获取Class类方法一:全限定类名
Class<?> aClass = Class.forName("reflection.study.bean.User");
System.out.println(aClass);
System.out.println("获取全类名:"+aClass.getName());
System.out.println("获取类名:"+aClass.getSimpleName());
// 获取Class类方法二:
Class<User> bClass = User.class;
System.out.println(bClass.getName());
// 获取Class类的方法三:通过实例对象获取
User user = new User();
Class<? extends User> cUser = user.getClass();
System.out.println(cUser.getSimpleName());
}