《Java基础知识》Java注解"@"详解
Java注解含义:
Java注解,顾名思义,注解,就是对某一事物进行添加注释说明,会存放一些信息,这些信息可能对以后某个时段来说是很有用处的。
Java注解又叫java标注,java提供了一套机制,使得我们可以对方法、类、参数、包、域以及变量等添加标准(即附上某些信息)。且在以后某个时段通过反射将标注的信息提取出来以供使用。
样例(实现一个自己的注解):
import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; @Target(value = {ElementType.TYPE}) @Retention(RetentionPolicy.RUNTIME) public @interface MyAnnotaion { String value(); }
import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; @Target(value = {ElementType.FIELD}) @Retention(RetentionPolicy.RUNTIME) public @interface MyFieldAnnotaion { String value(); String type(); String lengths(); }
import java.io.Serializable; @MyAnnotaion("student") public class Student implements Serializable { private static final long serialVersionUID = 1L; @MyFieldAnnotaion(value = "1",type = "int",lengths = "10") String id; @MyFieldAnnotaion(value = "蕾蕾",type = "String" ,lengths = "200") String name; public String getId() { return id; } public void setId(String id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } @Override public String toString() { return "Student{" + "id='" + id + '\'' + ", name='" + name + '\'' + '}'; } }
import org.apache.poi.ss.formula.functions.T; import java.lang.annotation.Annotation; import java.lang.reflect.Field; /** * 通过反射获取注解 */ public class AnnotaionDemo { public static void main(String[] args) throws Exception { Class<T> clazz = (Class<T>) Class.forName("demo.knowledgepoints.annotation.Student"); //判断注解是否存在 if(clazz.isAnnotationPresent(MyAnnotaion.class)){ System.out.println("存在注解:MyAnnotaion"); } //获取注解列表 Annotation[] annotaions = clazz.getAnnotations(); for (int i = 0; i < annotaions.length; i++) { System.out.println("注解:"+annotaions[i]); } //获取注解内容 MyAnnotaion myAnnotaion = clazz.getAnnotation(MyAnnotaion.class) ; System.out.println("注解的值为:"+myAnnotaion.value()); //获取方法上的注解内容 Field field = clazz.getDeclaredField("id"); //方法上注解是否存在 field.isAnnotationPresent(MyFieldAnnotaion.class); //方法注解列表 field.getAnnotations(); //获取方法上的注解内容 MyFieldAnnotaion myFieldAnnotaion = field.getAnnotation(MyFieldAnnotaion.class); System.out.println("value:"+myFieldAnnotaion.value()+"; type:"+myFieldAnnotaion.type()+"; lengths:"+myFieldAnnotaion.lengths()); } }
运行结果:
根据这个案例:
1. 注解实现需要关键字:@interface;
2. 在注解上我们还使用了注解 @Target,@Retention。这些被称为元注解,
Java中元注解有四个: @Retention @Target @Document @Inherited;
@Retention:注解的保留位置
@Retention(RetentionPolicy.SOURCE) //注解仅存在于源码中,在class字节码文件中不包含
@Retention(RetentionPolicy.CLASS) // 默认的保留策略,注解会在class字节码文件中存在,但运行时无法获得,
@Retention(RetentionPolicy.RUNTIME) // 注解会在class字节码文件中存在,在运行时可以通过反射获取到
@Target:注解的作用目标
@Target(ElementType.TYPE) //接口、类、枚举
@Target(ElementType.FIELD) //字段、枚举的常量
@Target(ElementType.METHOD) //方法
@Target(ElementType.PARAMETER) //方法参数
@Target(ElementType.CONSTRUCTOR) //构造函数
@Target(ElementType.LOCAL_VARIABLE)//局部变量
@Target(ElementType.ANNOTATION_TYPE)//注解
@Target(ElementType.PACKAGE) ///包
@Document:说明该注解将被包含在javadoc中
@Inherited:说明子类可以继承父类中的该注解
3. 直接里面可以写方法:String value();
外部使用注解可以将值写入,后续可以拿到该值进行使用。
可以提供默认值: String value() default "花花";
修改 AnnotaionDemo 的方法实现一个常用功能,通过注解将值注入实体类中:
import org.apache.poi.ss.formula.functions.T; import java.lang.reflect.Field; import java.lang.reflect.Method; /** * 通过反射获取注解 */ public class AnnotaionDemo { public static void main(String[] args) throws Exception { Student student = (Student) getbean("demo.knowledgepoints.annotation.Student"); System.out.println(student); } public static Object getbean(String className) throws Exception{ Class<T> clazz = (Class<T>) Class.forName(className); //判断注解是否存在(该注解被当成标记使用) if(!clazz.isAnnotationPresent(MyAnnotaion.class)){ throw new Exception("该类缺失注解“MyAnnotaion”,不能通过反射获取bean"); } //创建实体类 Object object = clazz.newInstance(); Field[] fields = clazz.getDeclaredFields(); for (int i = 0; i < fields.length; i++) { //获取字段名 String name = fields[i].getName(); //过滤序列 if (name.equals("serialVersionUID")) { continue; } //组装SET方法 Class<?> type = clazz.getDeclaredField(name).getType(); // 首字母大写 String replace = name.substring(0, 1).toUpperCase() + name.substring(1); Method setMethod = clazz.getMethod("set" + replace, type); //获取字段值 Field field = clazz.getDeclaredField(name); MyFieldAnnotaion myFieldAnnotaion = field.getAnnotation(MyFieldAnnotaion.class); String value = myFieldAnnotaion.value(); //执行set方法 if (value != null && !"".equals(value)) { // ---判断读取数据的类型(判断部分类型) if (type.isAssignableFrom(String.class)) { setMethod.invoke(object, value); } else if (type.isAssignableFrom(int.class) || type.isAssignableFrom(Integer.class)) { setMethod.invoke(object, Integer.parseInt(value)); } else if (type.isAssignableFrom(Double.class) || type.isAssignableFrom(double.class)) { setMethod.invoke(object, Double.parseDouble(value)); } else if (type.isAssignableFrom(Boolean.class) || type.isAssignableFrom(boolean.class)) { setMethod.invoke(object, Boolean.parseBoolean(value)); } } } return object; } }
运行结果:
案例中使用了反射:反射详解:https://www.cnblogs.com/jssj/p/11723910.html
总结语:注解功能在框架开发中被广泛使用:例如Spring,MyBatis等。注解的出现大大的减少了开发工作中的开发工作量。