注解
介绍
注解是Java 1.5 引入的,目前已被广泛应用于各种Java框架,如Hibernate,Jersey,Spring。注解相当
于是一种嵌入在程序中的 元数据 ,可以使用注解解析工具或编译器对其进行解析,也可以指定注解在编
译期或运行期有效。在注解诞生之前,程序的元数据存在的形式仅限于java注释或javadoc,但注解可以
提供更多功能,它不仅包含元数据,还能作用于运行期,注解解析器能够使用注解决定处理流程。
Annotation(注解)就是Java提供了一种元程序中的元素关联任何信息和任何元数据 (metadata)的途径和
方法。Annotation是一个接口,程序可以通过反射来获取指定程序元素的Annotation对象,然后通过
Annotation对象来获取注解里面的元数据。注解API非常强大,被广泛应用于各种Java框架。
作用
- 解释|注释
- 标志|标识
- 注解可以存在编译后的class的字节码文件中
- 在程序运行期间获取到注解配置的参数信息,再在程序中使用
- 大量的代替了配置文件的存在
- 可以定在任意位置具体要看注解类型在定义的时候如何规范
分类
- 按参数的个数
- 标识注解|标志注解
- 单值注解:即参数只有一个
- 完整注解:参数有多个
- 按注解的使用方法和注解
- jdk内置注解
- 自定义注解
- 元注解
jdk内置注解
-
@override
限定重写父类方法,若想要重写父类的一个方法时,需要使用该注解告知编译器我们正在重写一个方
法。如此一来,当父类的方法被删除或修改了,编译器会提示错误信息;或者该方法不是重写也会提示
错误。 -
@Deprecated
标记已过时,当我们想要让编译器知道一个方法已经被弃用(deprecate)时,应该使用这个注解。Java推
荐在javadoc中提供信息,告知用户为什么这个方法被弃用了,以及替代方法是什么public class Test_Deprecated { @Deprecated public static void testDeprecated(){ System.out.println("该方法已被弃用!"); } public static void testDeprecated(int a){ System.out.println("该方法很有用"+a); } }
在这里使用该注解当你在调用这个方法时会出现如下的情况、
-
@SuppressWarnings
抑制编译器警告,该注解仅仅告知编译器,忽略它们产生了特殊警告。如:在java泛型中使用原始类
型。其保持性策略(retention policy)是SOURCE,在编译器中将被丢弃。
元注解
元注解的作用就是负责注解其他注解。Java5.0定义了4个标准的 meta-annotation 类型,它们被用来提
供对其它 annotation类型作说明。Java5.0定义的元注解有四个,这些类型和它们所支持的类在
java.lang.annotation包中可以找到
-
@Target
用于描述注解的使用范围 ElementType 类型中定义使用范围
//此注解只能用在方法上 @Target(ElementType.METHOD) @interface TestMethod {}
-
@Retention
用于描述注解的生命周期 RetentionPolicy类型中定义生命周期
// 此注解可以用于注解类、接口(包括注解类型) 或enum声明 @Target(ElementType.TYPE) //该注解运行时有效。注解处理器可以通过反射,获取到该注解的属性值,从而去做一些运行时的逻辑处理 @Retention(RetentionPolicy.RUNTIME) @interface TestRn{ }
-
@Documented
表示使用该注解的元素。成为API的一部分
-
@inherited
表示一个在注解类型会自动继承
-
@Repeatable
某些情况下,一个程序元素需要使用多个同一种类型的注解。@Repeatable元注解,顾名思义,重复注
解,就是在声明创建注解的时候,指定该注解可以被同一个程序元素多次使用。
自定义注解
- @interface定义注解类型
- 默认隐式的实现java.lang.annotation.Annotation接口,所有注解类型扩展的公共接口
- 自定义的注解类型不能继承其他父类,实现其他接口
- 注解类型中可以定义属性 数据类型 属性名
- 注解类型中的属性数据类型可以为 基本数据类型 String 枚举 注解
- 当注解类型中的属性只有一个,建议属性名定义为value,赋值时可以省略属性名直接赋值
- 为属性通过defalut提供默认值
public class Test_FruitList {
public static void main(String[] args) throws IllegalAccessException {
FruitList fruitList = new FruitList();
fruitList = testFruitList(fruitList,FruitList.class);
System.out.println(fruitList);
}
public static FruitList testFruitList(FruitList list ,Class<FruitList> cls) throws IllegalAccessException {
//1.获取该类的所有字段
Field[] declaredFields = cls.getDeclaredFields();
//对字段数组进行遍历
for (Field declaredField : declaredFields) {
//2.判断该字段是否有值
if (declaredField.get(list)==null){
//3.判断字段上是否有注解
if (declaredField.isAnnotationPresent(Fruitnum.class)){
//4.如果有获取注解赋值
Fruitnum fruitnum = declaredField.getAnnotation(Fruitnum.class);
declaredField.set(list,fruitnum.value());
}
}
//5.如果没有不赋值
}
return list;
}
}
class FruitList{
@Fruitnum(20)
Integer apple;
@Fruitnum
Integer banana;
Integer pair;
public Integer getApple() {
return apple;
}
public FruitList() {
}
public void setApple(Integer apple) {
this.apple = apple;
}
public Integer getBanana() {
return banana;
}
public void setBanana(Integer banana) {
this.banana = banana;
}
public Integer getPair() {
return pair;
}
public void setPair(Integer pair) {
this.pair = pair;
}
@Override
public String toString() {
return "FruitList{" +
"apple=" + apple +
", banana=" + banana +
", pair=" + pair +
'}';
}
public FruitList(Integer apple, Integer banana, Integer pair) {
this.apple = apple;
this.banana = banana;
this.pair = pair;
}
}
@Target(ElementType.FIELD)//使用在字段上
@Retention(RetentionPolicy.RUNTIME)//在运行时使用
@interface Fruitnum{
int value()default 10;
}
this.banana = banana;
this.pair = pair;
}
}
@Target(ElementType.FIELD)//使用在字段上
@Retention(RetentionPolicy.RUNTIME)//在运行时使用
@interface Fruitnum{
int value()default 10;
}