《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 {</span><span style="color: rgba(0, 0, 255, 1)">private</span> <span style="color: rgba(0, 0, 255, 1)">static</span> <span style="color: rgba(0, 0, 255, 1)">final</span> <span style="color: rgba(0, 0, 255, 1)">long</span> serialVersionUID = 1L<span style="color: rgba(0, 0, 0, 1)">; @MyFieldAnnotaion(value </span>= "1",type = "int",lengths = "10"<span style="color: rgba(0, 0, 0, 1)">) String id; @MyFieldAnnotaion(value </span>= "蕾蕾",type = "String" ,lengths = "200"<span style="color: rgba(0, 0, 0, 1)">) String name; </span><span style="color: rgba(0, 0, 255, 1)">public</span><span style="color: rgba(0, 0, 0, 1)"> String getId() { </span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> id; } </span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">void</span><span style="color: rgba(0, 0, 0, 1)"> setId(String id) { </span><span style="color: rgba(0, 0, 255, 1)">this</span>.id =<span style="color: rgba(0, 0, 0, 1)"> id; } </span><span style="color: rgba(0, 0, 255, 1)">public</span><span style="color: rgba(0, 0, 0, 1)"> String getName() { </span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> name; } </span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">void</span><span style="color: rgba(0, 0, 0, 1)"> setName(String name) { </span><span style="color: rgba(0, 0, 255, 1)">this</span>.name =<span style="color: rgba(0, 0, 0, 1)"> name; } @Override </span><span style="color: rgba(0, 0, 255, 1)">public</span><span style="color: rgba(0, 0, 0, 1)"> String toString() { </span><span style="color: rgba(0, 0, 255, 1)">return</span> "Student{" + "id='" + id + '\'' + ", name='" + name + '\'' + '}'<span style="color: rgba(0, 0, 0, 1)">; }
}
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");
}</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">获取注解列表</span> Annotation[] annotaions =<span style="color: rgba(0, 0, 0, 1)"> clazz.getAnnotations(); </span><span style="color: rgba(0, 0, 255, 1)">for</span> (<span style="color: rgba(0, 0, 255, 1)">int</span> i = 0; i < annotaions.length; i++<span style="color: rgba(0, 0, 0, 1)">) { System.out.println(</span>"注解:"+<span style="color: rgba(0, 0, 0, 1)">annotaions[i]); } </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">获取注解内容</span> MyAnnotaion myAnnotaion = clazz.getAnnotation(MyAnnotaion.<span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)">) ; System.out.println(</span>"注解的值为:"+<span style="color: rgba(0, 0, 0, 1)">myAnnotaion.value()); </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">获取方法上的注解内容</span> Field field = clazz.getDeclaredField("id"<span style="color: rgba(0, 0, 0, 1)">); </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">方法上注解是否存在</span> field.isAnnotationPresent(MyFieldAnnotaion.<span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)">); </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">方法注解列表</span>
field.getAnnotations();
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">获取方法上的注解内容</span> MyFieldAnnotaion myFieldAnnotaion = field.getAnnotation(MyFieldAnnotaion.<span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)">); System.out.println(</span>"value:"+myFieldAnnotaion.value()+"; type:"+myFieldAnnotaion.type()+"; lengths:"+<span style="color: rgba(0, 0, 0, 1)">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");
}</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">创建实体类</span> Object object =<span style="color: rgba(0, 0, 0, 1)"> clazz.newInstance(); Field[] fields </span>=<span style="color: rgba(0, 0, 0, 1)"> clazz.getDeclaredFields(); </span><span style="color: rgba(0, 0, 255, 1)">for</span> (<span style="color: rgba(0, 0, 255, 1)">int</span> i = 0; i < fields.length; i++<span style="color: rgba(0, 0, 0, 1)">) { </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">获取字段名</span> String name =<span style="color: rgba(0, 0, 0, 1)"> fields[i].getName(); </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">过滤序列</span> <span style="color: rgba(0, 0, 255, 1)">if</span> (name.equals("serialVersionUID"<span style="color: rgba(0, 0, 0, 1)">)) { </span><span style="color: rgba(0, 0, 255, 1)">continue</span><span style="color: rgba(0, 0, 0, 1)">; } </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">组装SET方法</span> Class<?> type =<span style="color: rgba(0, 0, 0, 1)"> clazz.getDeclaredField(name).getType(); </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 首字母大写</span> String replace = name.substring(0, 1<span style="color: rgba(0, 0, 0, 1)">).toUpperCase() </span>+ name.substring(1<span style="color: rgba(0, 0, 0, 1)">); Method setMethod </span>= clazz.getMethod("set" +<span style="color: rgba(0, 0, 0, 1)"> replace, type); </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">获取字段值</span> Field field =<span style="color: rgba(0, 0, 0, 1)"> clazz.getDeclaredField(name); MyFieldAnnotaion myFieldAnnotaion </span>= field.getAnnotation(MyFieldAnnotaion.<span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)">); String value </span>=<span style="color: rgba(0, 0, 0, 1)"> myFieldAnnotaion.value(); </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">执行set方法</span> <span style="color: rgba(0, 0, 255, 1)">if</span> (value != <span style="color: rgba(0, 0, 255, 1)">null</span> && !""<span style="color: rgba(0, 0, 0, 1)">.equals(value)) { </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> ---判断读取数据的类型(判断部分类型)</span> <span style="color: rgba(0, 0, 255, 1)">if</span> (type.isAssignableFrom(String.<span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)">)) { setMethod.invoke(object, value); } </span><span style="color: rgba(0, 0, 255, 1)">else</span> <span style="color: rgba(0, 0, 255, 1)">if</span> (type.isAssignableFrom(<span style="color: rgba(0, 0, 255, 1)">int</span>.<span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)">) </span>|| type.isAssignableFrom(Integer.<span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)">)) { setMethod.invoke(object, Integer.parseInt(value)); } </span><span style="color: rgba(0, 0, 255, 1)">else</span> <span style="color: rgba(0, 0, 255, 1)">if</span> (type.isAssignableFrom(Double.<span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)">) </span>|| type.isAssignableFrom(<span style="color: rgba(0, 0, 255, 1)">double</span>.<span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)">)) { setMethod.invoke(object, Double.parseDouble(value)); } </span><span style="color: rgba(0, 0, 255, 1)">else</span> <span style="color: rgba(0, 0, 255, 1)">if</span> (type.isAssignableFrom(Boolean.<span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)">) </span>|| type.isAssignableFrom(<span style="color: rgba(0, 0, 255, 1)">boolean</span>.<span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)">)) { setMethod.invoke(object, Boolean.parseBoolean(value)); } } } </span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> object;
}
}
运行结果:
案例中使用了反射:反射详解:https://www.cnblogs.com/jssj/p/11723910.html
总结语:注解功能在框架开发中被广泛使用:例如 Spring,MyBatis 等。注解的出现大大的减少了开发工作中的开发工作量。