概述
(1.)注解可以理解为一种使用相关信息来绑定Java文件元素的方式
(2.)Java中常见的注解
- @Override: 表示必须对方法重写
- @Deprecated : 表示方法过时
- @SuppresWarning : 表示忽略警告
- @FunctionalInterface : 表示函数式接口
(3.)按照运行机制分类: - 源码注解: 注解只在源码中存在,当编译生成.class文件的时候,就不存在了
- 编译时注解: 注解在源码和.class文件中存在,当程序运行的时候它就不存在了
- 运行时注解: 在运行的时候还能够起作用的注解,它会动态影响到程序执行逻辑
- 元注解: 对注解进行注解
元注解:
@Target:标识它所标识的注解能够作用在什么元素上
如果一个注解的@Target上面的注解范围显示了ANNOTATION_TYPE,那么表示该注解是元注解
@Retention: 表示它所标识的注解的生命周期
RetentionPolicy.SOURCE:表示该注解只在源码中存在
RetentionPolicy.CLASS: 表示该注解只在源码和编译时存在
RetentionPolicy.RUNTIME: 表示该注解在源码和编译时以及运行时存在
@Inherited: 表示该注解可以被继承
@Document: 表示该注解可以在生成API文档的时候显示在文档上
通过反射可以获取到字节码文件对象,通过字节码文件对象就能够获取到所有的有关该类的元素 然后注解也是类元素的一种,所以可以获取到对应的注解,但是这个注解必须是运行时注解
- A getAnnotation(Class annotationClass)
- Annotation[] getAnnotations()
- Annotation[] getDeclaredAnnotations()
- boolean isAnnotationPresent(Class<? extends Annotation> annotationClass)
public class AnnotationDemo01 {
public static void main(String[] args) throws ClassNotFoundException {
Class<?> c = Class.forName("com.xt.annotationdemo02.Student");
// 判断该字节码文件中是否存在@MyAnnotation注解
boolean isAnnotationPresent = c.isAnnotationPresent(MyAnnotation.class);
if (isAnnotationPresent) {
MyAnnotation annotation = c.getDeclaredAnnotation(MyAnnotation.class);
System.out.println(annotation.value());
}
System.out.println("----------成员方法-------------");
Method[] methods = c.getMethods();
for (Method m : methods) {
boolean present = m.isAnnotationPresent(MyAnnotation.class);
if (present) {
MyAnnotation declaredAnnotation = m.getDeclaredAnnotation(MyAnnotation.class);
System.out.println(declaredAnnotation.value());
}
}
System.out.println("---------构造方法--------------");
Constructor<?>[] constructors = c.getConstructors();
for (Constructor<?> constructor : constructors) {
boolean present = constructor.isAnnotationPresent(MyAnnotation.class);
if (present) {
MyAnnotation declaredAnnotation = constructor.getDeclaredAnnotation(MyAnnotation.class);
System.out.println(declaredAnnotation.value());
}
}
System.out.println("---------成员变量--------------");
Field[] fields = c.getDeclaredFields();
for (Field field : fields) {
boolean present = field.isAnnotationPresent(MyAnnotation.class);
if (present) {
MyAnnotation declaredAnnotation = field.getDeclaredAnnotation(MyAnnotation.class);
System.out.println(declaredAnnotation.value());
}
}
System.out.println("---------toString--------------");
System.out.println("获取tostring方法");
boolean annotationPresent = c.isAnnotationPresent(Override.class);
if (annotationPresent) {
MyAnnotation annotation = c.getDeclaredAnnotation(MyAnnotation.class);
System.out.println(annotation.value());
}
System.out.println("---------获取PrimaryStudent上的注解--------------");
Class<?> c2 = Class.forName("com.xt.annotationdemo02.PrimaryStudent");
boolean result = c2.isAnnotationPresent(MyAnnotation.class);
System.out.println(result);
}
}
@MyAnnotation("T_STU")
class Student{
@MyAnnotation("NAME")
private String name;
@MyAnnotation("AGE")
private int age;
@MyAnnotation("STU")
public Student() {
super();
}
public Student(String name, int age) {
super();
this.name = name;
this.age = age;
}
@MyAnnotation("getName")
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
@MyAnnotation("setAge")
public void setAge(int age) {
this.age = age;
}
@MyAnnotation("I'm a toString method")
@Override
public String toString() {
return "Student [name=" + name + ", age=" + age + "]";
}
}
class PrimaryStudent extends Student{
}
@Inherited
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE,ElementType.FIELD,ElementType.METHOD,ElementType.CONSTRUCTOR})
@interface MyAnnotation{
String value();
}
使用注解编写工具类实现Bean和Map之间的转换
/*
- 书写一个工具类
- 将 Map --> JavaBean
- JavaBean --> Map
*/
public class AnnotationTest {
public static void main(String[] args) throws InstantiationException, IllegalAccessException, NoSuchMethodException, SecurityException, IllegalArgumentException, InvocationTargetException {
// Map<String, Object> map = new HashMap<String, Object>();
// map.put("name", "张三");
// map.put("age", 18);
//
// User user = PojoMappingUtils.mapToBean(map, User.class);
// System.out.println(user);
//
// Map<String, Object> map2 = new HashMap<String, Object>();
// map2.put("name", "张三老师");
// map2.put("age", 18);
// map2.put("address", "北京西路");
// map2.put("tid", "1001");
// Teacher t = PojoMappingUtils.mapToBean(map2, Teacher.class);
// System.out.println(t);
Teacher t = new Teacher();
t.setTid("1001");
t.setName("老师");
t.setAge(18);
t.setAddress("北京西路");
User user = new User();
user.setName("zhangsan");
user.setAge(18);
Map<String, Object> map = PojoMappingUtils.beanToMap(user);
Set<String> keys = map.keySet();
for (String key : keys) {
System.out.println(key + "=" + map.get(key));
}
}
}
@Target({ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
public @interface Column {
String value();
}
/**
* 这是一个利用 反射 + 注解 + 泛型 封装的map和javabean相互转换的一个工具类
* @author xyr
*/
public class PojoMappingUtils {
private PojoMappingUtils() throws IllegalAccessException {
}
// User Emlopyee 外界告诉我这个方法 你到底希望我转成什么 bean
public static <T> T mapToBean(Map<String, Object> map, Class<T> clazz) throws InstantiationException, IllegalAccessException, NoSuchMethodException, SecurityException, IllegalArgumentException, InvocationTargetException {
T t = clazz.newInstance();
Field[] fields = clazz.getDeclaredFields();
for (Field field : fields) {
if (field.isAnnotationPresent(Column.class)) {
Column columnAnnotation = field.getAnnotation(Column.class);
if (columnAnnotation != null) {
Object o = map.get(columnAnnotation.value());
if (o != null) {
String fieldName = field.getName();
Method method = clazz.getMethod("set" + fieldName.substring(0, 1).toUpperCase() + fieldName.substring(1), o.getClass());
method.invoke(t, o);
}
}
}
}
return t;
}
@Test
public void testBeanToMap() throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {
User user = new User();
user.setName("zhangsan");
user.setAge(18);
Map<String, Object> map = beanToMap(user);
System.out.println(map);
}
public static <T> Map<String, Object> beanToMap(T t) throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException{
// 创建容器来装载bean中的数据
Map<String, Object> map = new HashMap<String, Object>();
// 获取bean多对应的字节码文件对象
Class<?> c = t.getClass();
// 获取到bean中所有的成员变量对象
Field[] fields = c.getDeclaredFields();
for (Field field : fields) {
// 获取到每一个成员变量对象 name 变量
if (field.isAnnotationPresent(Column.class)) {
Column columnAnnotation = field.getAnnotation(Column.class);
if (columnAnnotation != null) {
String value = columnAnnotation.value(); // name字符串
// 获取字段名称 name
String fieldName = field.getName();
// 获取getName方法
Method method = c.getMethod("get" + fieldName.substring(0, 1).toUpperCase() + fieldName.substring(1));
Object getValue = method.invoke(t);
map.put(value, getValue);
}
}
}
return map;
}
}
public class User {
@Column("name")
private String name;
@Column("age")
private Integer age;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
@Override
public String toString() {
return "User [name=" + name + ", age=" + age + "]";
}
}