什么是注解
引用书中的定义:
注解(也被称为元数据)为我们在代码中添加信息提供了一种形式化的方法, 使我们可以在后续的某个时刻非常方便的使用这些数据。(Thinking In Java中文版4)
注解能够以将有编译器来测试和验证的格式, 存储有关程序的额外信息。
主要依赖Java中的反射机制。
常见注解
Java内置了几种注解,开发中经常使用到:
- @Override : 子类重写父类的方法, 建议添加@Override注解, 借助编译器完成检查防止参数错误,拼写错误等
- @Deprecated : 常见与第三方jar包,声明方法废弃, 不建议使用,如果使用编译器会提示warning
- @SuppressWarnings:常用于不检查类型检查
还有一种注解也经常使用, @Test编写单元测试时使用, 来自JUnit.
注解定义
注解的定义与接口类似, 多了@符号,示例如下:
package com.notepad.thinkingnote.annotations;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* Description: 用于字段描述的注解
* <p>
* 用于字段的描述, 运行期也保留
* </p>
* Create: 2018/7/15 17:58
*
* @author Yang Meng(eyangmeng@163.com)
*/
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Description {
String value() default "";
}
示例中用到@Target和@Retention注解, 这两个注解为元注解(Java内置)。
- @Target:
- 表示注解用到的位置, 示例中FIELD表示注解位置为域声明, 定义到Class的成员变量;其他有METHOD(方法), TYPE(类,接口)等
- @Retention:
- 表示需要在什么级别保存该注解信息, 示例中RUNTIME表示在保存到运行时(因为我们后面需要利用反射机制处理该注解)
使用注解
注解的使用同@Override注解方法一致,示例如下:
定义Entity
package com.notepad.thinkingnote.annotations;
/**
* Description: 实体定义
* <p>
* 使用Description注解
* </p>
* Create: 2018/7/15 18:02
*
* @author Yang Meng(eyangmeng@163.com)
*/
public class Entity {
@Description("实体名称")
private String name;
@Description("实体UID")
private String uid;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getUid() {
return uid;
}
public void setUid(String uid) {
this.uid = uid;
}
}
注解处理器
对于自定义的注解,我们需要编写注解解释器以使用这些注解, 否则注解反而不是直接注释来的方便。对应示例中的Description注解, 给出处理器示例,完成的功能时输出字段描述信息, 示例如下:
package com.notepad.thinkingnote.annotations;
import java.lang.reflect.Field;
/**
* Description: Entity关于Description的注解处理器
* <p>
* Create: 2018/7/15 18:33
*
* @author Yang Meng(eyangmeng@163.com)
*/
public class EntityShow {
/**
* 显示Entity的字段描述信息
*
* @return string
*/
public static String showFieldDescription(Entity entity) {
StringBuilder stringBuilder = new StringBuilder(entity.getClass().getSimpleName()).append(":{ \n");
Field[] fields = entity.getClass().getDeclaredFields();
for (Field f : fields) {
stringBuilder.append(f.getName());
Description fieldDes = f.getAnnotation(Description.class);
if (fieldDes != null) {
stringBuilder.append(":").append(fieldDes.value());
}
stringBuilder.append("\n");
}
stringBuilder.append("}\n");
return stringBuilder.toString();
}
public static void main(String [] args) {
Entity entity = new Entity();
entity.setName("笔记本电脑");
entity.setUid("20180715");
System.out.println(showFieldDescription(entity));
}
}
总结
注解可以很方便我们的编程, 相对于注释,注解可以利用编译器做一些事情, 利用Java的反射机制实现我们想要的功能。为此, 我们还需要深入了解Java反射机制。
参考
Thinking In Java 中文第四版 - 第20章