注解
注解Annotation是一种元数据形式。属于java的一种数据类型,其地位和类、接口、数组、枚举这些都是一样的。
注解Annotation是书写在java代码中的,但是其中书写的位置被固定为类、方法、变量、参数和包的声明部分
注解的分类
1、JDK自带的注解
- @Override 用于方法,表示强行检测该方法是否重写父类方法,如果没有重写则编译错误
- @Deprecated 用于标识指定类或指定方法,为过时的类或方法。
2、开发者自定义的注解
public @interface MyAnnotation {
}
注解本质是一种特殊的接口。在底层实现上,所有定义的注解都会自动继承java.lang.annotation.Annotation。
public @interface MyAnnotation {
public String name();
public int age();
int[] array();
}
在注解中,只能定义注解元素。注解元素写法和抽象方法类似,但是本质是属性。所以,注解元素的括号中,不能加参数。
注解元素说明
1、注解元素的访问修饰符只能是public,不写也默认为public。
2、注解元素的类型只能是基本数据类型、String、Class、注解类型、枚举类型、以及上面这几种的一维数组。
3、注解元素的名字应该为名词形式。如果一个注解中只有一个类型元素,建议把名字取成value,方便后面操作。
4、()不是定义方法参数列表的地方,也不能在括号中定义任何参数,就是一个特殊的语法
5、default代表默认值,值必须和该注解元素的类型一致。
6、如果没有默认值,代表后面使用时必须给该类型元素赋值。
元注解
专门修饰注解的注解,是为了更好的设计自定义注解的细节而专门设计的。
**@target 元注解:**用来专门限定某个自定义注解能被应用到哪些java元素上。比如,某个注解是否可以在类、方法、属性上使用。
@Target({ElementType.FIELD,ElementType.METHOD,ElementType.TYPE})
public @interface MyAnnotation {
public String name();
public int age();
int[] array();
}
@Target({ElementType.FIELD,ElementType.METHOD,ElementType.TYPE})表示该注解可以在属性、方法、类中使用。
**@Retention 元注解:**是用来限定某个自定义注解的生命周期
@Retention(RetentionPolicy.SOURCE)
仅存在java源文件中,在运行时不能得到任何数据、和注释没什么区别@Retention(RetentionPolicy.CLASS)
被编译到class文件中,编译器可以在编译时根据注解做一些处理动作。但在运行时,JVM会忽略它,在运行期也不能读取到。@Retention(RetentionPolicy.RUNTIME)
该注解可以在运行期的加载阶段被加载到Class对象中。在程序运行阶段,可以通过反射得到该注解。
其它元注解:
@Documented注解,是被用来指定自定义注解是否能随着被定义的java文件生成到javadoc
文档中。
@Inherited 注解,是指定某个自定义注解如果写在了父类的声明部分,那么子类的声明部分也能自动拥有该注解。
注解的语法
1、定义一个注解时,没有定义注解元素。那么在使用时,可以省去括号
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Id {
}
@Id
@Column("pk_employeeId")
private Integer id;
2、定义一个注解元素时,如果该注解元素是数组,且数组只有一个值。那么,可以直接书写为类型名=类型值。
@Target({ElementType.FIELD,ElementType.METHOD,ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface MyAnnotation {
int[] array();
}
@MyAnnotation(array =2)
public class MyObj {
}
运行时得到注解信息
Class objClass = MyObj.class;
//判断指定类中,是否存在MyAnnotation注解
if (objClass.isAnnotationPresent(MyAnnotation.class)) {
//得到指定类中,MyAnnotation注解对象
MyAnnotation my = (MyAnnotation) objClass.getAnnotation(MyAnnotation.class);
//得到注解元素的值
String name = my.name();
int age = my.age();
int[] array = my.array();
System.out.println(name + " " + age + " " + Arrays.toString(array));
注解元素的默认值
public int age() default 18;
注解元素加上默认值之后,在使用该注解时,可以不对该注解元素赋值。得到的注解元素的值就为默认值。但是,如果使用该注解时,给该注解元素赋了值,以新的赋值作为该注解元素的值。
使用value做注解元素名
定义注解时,如果只有一个注解元素,并且该注解元素名为value,那么在使用注解时,可以只写注解元素值,不写注解元素名。
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface TestAnnotation {
public String value();
}
@TestAnnotation("ok")
public class MyObj {
}
XML和注解的比较
XML称为可扩展的标记语言,被大量用来作为不同平台之间数据传递的标准格式。
注解Annotation是java语言独有的,只能java用,并且其设计目的就是为了做配置的。
XML用途比java注解要广泛得多,它不限语言,只要需要表示数据的地方都可以使用,这是java注解绝对不可比拟的。所有,java注解要替代XML是不可能的。
XML优点:
1.可扩展性强,XML和它的定义文件(DTD、Schema)都是文本文件,添加或修改都很方便。
2、满足开闭原则,XML的配置文件是独立于java代码之外的,所以如果要修改配置是不需要改动java代码的。
缺点:
- 解析麻烦,需要第三方类库配合
- 配置文件过多后,会导致项目管理、维护变得困难。
- 在做代码的关联配置时麻烦,会让开发人员不断在java代码和XML配置文件之间来回切换。
- 查错困难,XML只是文本文件,很多报错只能在运行期间体现,IDE集成开发坏境不能在编译期排查。
注解优点:
- JDK自带反射方式解析,不引入第三方库
- 直接配置在java源代码中,所以不会引入额外的配置文件,项目管理和维护变得简单
- 无论是定义、配置还是解析都是java代码,所以不存在配置时需要在不同语法格式中切换的问题
- idea支持度高,排查错误方便,提高开发效率
缺点:
- 任何对配置、对定义的修改都需要改动java代码,然后重新编译,重新打包应用。
- 不是通用标准,只能在Java中使用
把与代码关联度不高,并且改动可能性大的配置写在XML文件中,专门配置java代码级别关联度的,以后改动度小的则使用注解Annotation。