关公举目一望,谓操曰:“吾观颜良,如插标卖首耳!”
Java 注解并不是程序,只是 Java 程序中的一个标识,Java 程序可以通过这个标识进行一些判断,执行不同的计算和流程。
在 三国演义
中,关公说颜良是插标卖首,这个所谓的 标
其实和 Java 中的注解有异曲同工之意,都是在人或者代码的头上标注一个东西。
现在,我们就用 Java 注解的功能模拟一下关公斩颜良诛文丑的过程吧。
人
首先,先创建一个 Person 类,该类代表了所有人,这个类的实例对象,可能是关公,也可能是颜良文丑,也可能只是一个普通的小兵。
public class Person {
/**
* 是否已死亡
*/
private boolean die = false;
/**
* 是否死亡
*
* @return 是否死亡
*/
public boolean isDie() {
return this.die;
}
/**
* 被杀
*/
public void beKilled() {
this.die = true;
}
/**
* 杀人
*
* @param person 被杀的人
*/
public void killed(Person... persons) {
for (Person person : persons) {
if (person != null) {
person.beKilled();
}
}
}
}
标(注解)
其次,应该创建一个 Java 注解,这个注解也就是关公所谓的 标
,可以在这个标上添加姓名属性,这样就可以通过这个 标
找到对应的角色。
/**
* <p>- @Target(ElementType.FIELD) 该注解只允许在类属性上标注</p>
* <p>- @Retention(RetentionPolicy.RUNTIME) 该注解保留到运行时</p>
* <p>- @Inherited 该注解会被子类继承</p>
* <p>- @Documented 该类会被 javadoc 生成的文档显示出来</p>
*/
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
@Inherited
@Documented
public @interface Name {
String value() default "小兵";
}
战场
既然一切准备就绪,那就可以布置战场了,创建一个战争 Java 类表示战场。
/**
* 关公举目一望,谓操曰:"吾观颜良,如插标卖首耳!"
*/
public class War {
// 战场中的角色
private Person person1 = new Person();
private Person person2 = new Person();
private Person person3 = new Person();
private Person person4 = new Person();
private Person person5 = new Person();
private Person person6 = new Person();
public static void main(String[] args) throws IllegalAccessException {
War war = new War();
war.start();
}
/**
* 战争开始了
*/
public void start() throws IllegalAccessException {
Person 关羽 = findPerson("关羽");
Person 颜良 = findPerson("颜良");
Person 文丑 = findPerson("文丑");
System.out.println();
checkStatus();
if (关羽 != null) {
关羽.killed(颜良, 文丑);
checkStatus();
System.out.println("关羽" + (颜良 == null ? "" : "斩颜良") + (文丑 == null ? "" : "诛文丑"));
}
}
/**
* 通过姓名找到注解标识了姓名的对应角色
*
* @param name 姓名
* @return 注解标识了姓名的对应角色
*/
public Person findPerson(String name) throws IllegalAccessException {
Field[] fields = War.class.getDeclaredFields();
for (Field field : fields) {
if (field.isAnnotationPresent(Name.class)) {
Name annotation = field.getAnnotation(Name.class);
if (annotation.value().equals(name)) {
System.out.print(name + "在战场上\t");
return (Person) field.get(this);
}
}
}
System.out.print(name + "不在在战场上\t");
return null;
}
/**
* 检查当前战场上使用注解标注了姓名的角色的生死
*/
public void checkStatus() throws IllegalAccessException {
Field[] fields = War.class.getDeclaredFields();
for (Field field : fields) {
if (field.isAnnotationPresent(Name.class)) {
Name annotation = field.getAnnotation(Name.class);
Person person = (Person) field.get(this);
if (person.isDie()) {
System.out.print(annotation.value() + "死了\t");
} else {
System.out.print(annotation.value() + "活着\t");
}
}
}
System.out.println();
}
}
开战
战争开始
模拟战争开始,直接先执行 main
方法。
战争结果:
关羽不在在战场上 颜良不在在战场上 文丑不在在战场上
颜良进入战场
在 War
类的某个 Person 类型的属性上,注解上 @Name("颜良")
注解,标注姓名。
@Name("颜良")
private Person person4 = new Person();
战争结果:
关羽不在在战场上 颜良在战场上 文丑不在在战场上
颜良活着
关羽进入战场
在 War
类的某个 Person 类型的属性上,注解上 @Name("关羽")
注解,标注姓名。
@Name("关羽")
private Person person6 = new Person();
战争结果:
关羽在战场上 颜良在战场上 文丑不在在战场上
颜良活着 关羽活着
颜良死了 关羽活着
关羽斩颜良
文丑进入战场
在 War
类的某个 Person 类型的属性上,注解上 @Name("文丑")
注解,标注姓名。
@Name("文丑")
private Person person5 = new Person();
战争结果:
关羽在战场上 颜良在战场上 文丑在战场上
颜良活着 文丑活着 关羽活着
颜良死了 文丑死了 关羽活着
关羽斩颜良诛文丑
战争结束
关公纵马上山,众将尽皆称贺。公献首级于操前。操曰:“将军真神人也!”
在这段 Java 程序中,Java 代码始终没有任何改变,仅仅只是添加了一些注解,最后的运行结果就完全不一样。这就是 Java 注解的功能,虽然本身不是程序代码的一部分,但是却是代码的标识,可以在程序运行的时候,通过这个标识进行一些判断,执行不同的计算和流程。
现在的大部分的 Java 框架,都有基于 Java 注解的使用版本,原理都是一样的。
本身就是在框架中对框架自定义的注解进行了一些程序判断和处理,使用者只需要在一些代码上标识一些注解,程序就可以按照框架的处理逻辑对这些代码进行处理。
Spring、MyBatis、Hibernate 等框架尽皆如此。