1 注解的介绍
注解:
jdk1.5版本的特性, 是一个引用数据类型(类,接口,枚举同一级别)
作用:
1 对代码进行解释说明,可以生成API文档
2 检查代码是否有错误(使用时添加@Override)
3 对代码分析,可起到代替配置文件的作用
JDK注解说明:
@Override 检测方法是否为重写方法
jdk1.5版本,支持父类的方法重写jdk1.6版本,支持接口的方法重写
@Deorecated 表示方法已经过时,不推荐使用.(调用方法时会有横线,可以使用. 一般官方废除方法,一定会提供一个新的可使用的方法)
@SupperssWarnings 消除警告(常用@SupperssWarnings("all"))
2 注解的格式
自定义注解格式
修饰符 @interface 注解名{
属性
}
属性的定义格式
- 数据类型 属性名();-->没有默认值的-->需要后面赋值
- 数据类型 属性名() default 默认值;-->可以改变的
定义的属性类型
- 八种基本数据类型(int,float,boolean,byte,double,char,long,short)
- String类型,Class类型,枚举类型,注解类型
- 以上所有类型的一维数据.
案列
public @interface Food {
//食物名
String name();
//价格
double price();
//配料
String[] compose();
//数量
//Integer count();错误,不能使用包装类
//int count() default 10;这个是可以的,定义属性的时候可以指定默认值
}
3 注解的使用
@Food(name="番茄炒蛋",price=12.00,compose={"番茄","鸡蛋"})
pubilc class TomatoAndEgg{
}
说明:
- 空注解可以直接使用,不需要赋初值
- 同一个对象中不能连续使用同一个注解多次,但是可以使用多个不同的注解.(注解解析的时候通过反射去解析,多个相同注解,也只会有一个有用)
- 如果注解中有属性,属性一定要赋初值,有多个属性,使用逗号
,隔开.(一般的注释中会给一个默认值) - 注解中属性如果有默认值(初值),可以不赋值,反之必须赋初值.
- 注解中只有一个属性,且属性名为
value,我们使用注解时,可以不用写属性名
4 案列1
@Food(name="番茄炒蛋",price=12.00,compose={"番茄","鸡蛋"})
public class TomatoAndEgg {
public static void main(String[] args) throws ClassNotFoundException {
//1.反射带有注解得类
Class c = Class.forName("com.cf.TomatoAndEgg");
//2.判断这个类上是否有注解
boolean b = c.isAnnotationPresent(Food.class);
System.out.println(b);
if (b){
Food food = (Food) c.getAnnotation(Food.class);
//获取注解中的属性值
System.out.println("菜名:"+food.name());
System.out.println("价格:"+food.price());
System.out.println("配料:"+ Arrays.toString(food.compose()));
}
}
}
/**
Q:结果答应为false,TomatoAndEgg类上有注解,为什么程序判断没有?
A:因为缺少了元注解的管理,注解默认是存在源码中,不在内存中,无法通过反射获取注解属性.
*/
5 元注解
元注解: JDK自带的注解, 管理其他的注解.(自定义的注解)
元注解功能:
- 控制自定义的注解,可以放置的位置(类/方法/变量/包...)
- 控制注解的生命周期
元注解属性:
-
@Target说明其他注解,出现的位置.- ElementType[] value(); 数组,可以赋值多个(ElementType是数据类型,是枚举的属性,都是静态修饰,直接类名调用)
TYPE可以写在类上FIELD可以写在成员变量METHOD可以写在方法上PARAMETER可以写在方法参数上CONSTRUCTOR可以写在构造方法上
- ElementType[] value(); 数组,可以赋值多个(ElementType是数据类型,是枚举的属性,都是静态修饰,直接类名调用)
-
@Retention说明其他注解的生命周期- RetentionPolicy value(); 不是数组,只能赋值一个(枚举类型,属性都是静态修饰,直接类名调用)
SOURCE默认级别, 注解仅存在于源码中(java文件中,class文件中没有,方法区没有)CLASS注解存在于编译后的class文件中,方法区没有RUNTIME注解存在运行时期的内存中,方法区中存在.(只有方法区中出现,才可以利用反射获取)
- RetentionPolicy value(); 不是数组,只能赋值一个(枚举类型,属性都是静态修饰,直接类名调用)
==ps : @Override 只是检测方法是否为重写方法==
6 案列1plus
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface Food {
//食物名
String name();
//价格
double price();
//配料
String[] compose();
}
@Food(name="番茄炒蛋",price=12.00,compose={"番茄","鸡蛋"})
public class TomatoAndEgg {
public static void main(String[] args) throws ClassNotFoundException {
//1.反射带有注解得类
Class c = Class.forName("com.cf.TomatoAndEgg");
//2.判断这个类上是否有注解
boolean b = c.isAnnotationPresent(Food.class);
System.out.println(b);
if (b){
Food food = (Food) c.getAnnotation(Food.class);
//获取注解中的属性值
System.out.println("菜名:"+food.name());
System.out.println("价格:"+food.price());
System.out.println("配料:"+ Arrays.toString(food.compose()));
}
}
}
/**
运行结果如下:
true
菜名:番茄炒蛋
价格:12.0
配料:[番茄, 鸡蛋]
*/