概念:
什么是注解?
是JDK1.5推出的新特性
- 对程序进行标注和解释
- 给类增加额外的信息
- 注解可以保存一些简单的数据
注解和注释的区别
注释: 给程序员看的
注解: 给编译器看的
使用注解进行配置配置的优势
代码更加简洁,方便
注解也可以代替xml
注解的作用:
- 编写文档:通过代码里标识的注解生成文档【生成文档doc文档】
- 编译检查:通过代码里标识的注解让编译器能够实现基本的编译检查【Override】
- 代码分析:通过代码里标识的注解对代码进行分析【使用反射】
JDK自带注解:
注解名 | 说明 |
---|---|
@Overridet | 描述子类重写父类的方法 |
@Deprecated | 描述方法过时 |
@SuppressWarnings | 压制警告 |
public class Zi extends Fu{
@Override
// 告诉编译器这个是重写了父类中的show方法
public void show() {
System.out.println("子类方法");
}
@Deprecated
public void method(){
System.out.println("表示是一个过时的方法");
}
@SuppressWarnings(value = "all")
public void method2(){
// 如果有一个类/方法/变量定义好以后没有使用,那么idea就会让它变成灰色,提醒你,这是没有使用过的,
// 可以使用SuppressWarnings(压制所有警告),放在类上面也可以的,就等于压制整个类
int a = 1;
int b = 2;
}
}
自定义注解:
格式:
public @interface 注解名称 {
public 属性类型 属性名() default 默认值 ;
修饰符只能是public也可以不写,
}
接口
public @interface Inter { }
枚举
public enum Aume {SPRING,SUMMER;}
public @interface Zdyzj {
//定义一个基本类型的属性
int a() default 1998;
//定义一个String类型的属性
String name() default "itzhuzhu";
//定义一个Class类型的属性
Class clazz() default Aume.class;
//定义一个注解类型的属性
Inter inter() default @Inter;
//定义一个枚举类型的属性
Aume au() default Aume.SPRING;
//以上类型的一维数组
// int数组
int[] IntArr() default {1, 2, 3, 4, 5};
//枚举数组
Aume[] AumeArr() default {Aume.SPRING, Aume.SUMMER};
//特殊属性:value、使用注解的时候,如果只需要给注解的value属性赋值。那么value就可以省略
String value();
}
//在使用注解的时候如果注解里面的属性没有指定默认值。
//那么我们就需要手动给出注解属性的设置值。
//@Anno1(name = "itzhuzhu")
@Anno1("abc") // 如果只有一个属性需要赋值,并且属性的名称是value,则value可以省略,直接定义值即可
public class AnnoDemo {
}
@Demo04(price = 6, name = "haha")
public class Demo03 {
@Demo04(name="hehe")
public static void main(String[] args) {
}
}
public @interface Demo04 {
String name();
double price() default 8.88;
}
元注解:
元注解是用来描述注解的注解用的
元注解名 | 说明 |
---|---|
@Target | 指定了注解能在哪里使用 |
@Retention | 限制注解能够存活到什么时候,默认是存活到CLASS阶段 |
@Inherited | 表示修饰的自定义注解可以被子类继承 |
@Documented | 表示该自定义注解,会出现在API文档里面。 |
自定义注解类:
@Target({ElementType.TYPE,ElementType.FIELD,ElementType.METHOD}) //注解在哪里可以使用依次代表(类、成员变量、方法)
@Retention(value = RetentionPolicy.RUNTIME) //生命周期
@Inherited
@Zdyzj("itzhuzhu")
public @interface Test {}
使用注解类:
public class UserTest {
@Test
public void show() {
System.out.println("show注解");
}
@Test
public void method() {
System.out.println("method注解");
}
}
继承注解的父类:
@Test
public class Fu {}
继承注解的子类:
public class Zi extends Fu{
public void show(){
System.out.println("子类方法");
}
}
测试类:
public class Demo {
public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException, InvocationTargetException {
//通过反射获取UseTest类的字节码文件对象
Class<?> aClass = Class.forName("zhujie.yuanzhujie.UserTest");
//创建对象
Object o = aClass.newInstance();
//通过反射获取这个类里面所有的方法对象
Method[] methods = aClass.getDeclaredMethods();
//遍历数组,得到每一个方法对象
for (Method method : methods) {
// isAnnotationPresent(Class<? extends Annotation> annotationClass):判断当前方法上是否有指定的注解。
// 参数:注解的字节码文件对象
// 返回值:布尔结果。 true 存在 false 不存在
if (method.isAnnotationPresent(Test.class)) {
method.invoke(o);
}
}
// 注解继承
Class<?> aClass1 = Class.forName("zhujie.yuanzhujie.Zi");
// 获取注解,返回true说明就是继承了
System.out.println(aClass1.isAnnotationPresent(Test.class));
}
}
// @Target(ElementType.PACKAGE) // 注解只能放在包上
// @Target(ElementType.TYPE) // 注解只能放在类和接口上
// @Target(ElementType.FIELD) // 注解只能放在成员变量上
// @Target(ElementType.CONSTRUCTOR) // 注解只能放在构造器上
// @Target(ElementType.METHOD) // 注解只能放在成员方法上
// @Target(ElementType.LOCAL_VARIABLE) // 注解只能放在局部变量上
// @Target({ElementType.METHOD, ElementType.LOCAL_VARIABLE}) // 注解放在多个位置上
@Retention(RetentionPolicy.RUNTIME)
public @interface MyAnno4 {
}
注解解析:
什么是注解解析?
得到注解中的属性数据
注解解析相关接口?
方法名 | 说明 |
---|---|
T getAnnotation(Class annotationClass) | 获取指定类型的注解 |
Annotation[] getAnnotations() | 获取所有注解 |
boolean isAnnotationPresent(Class annotationClass) | 判断是否有指定的注解 |
实现类: Class, Constructor, Field, Method
如何解析注解?
- 注解在谁头上就用谁来获取
- 注解在构造方法上,使用Constructor来获取
- 注解在成员方法上,使用Method来获取
- 注解在成员变量上,使用Field来获取
// 我们点左边绿色的三角形,程序就运行起来的.
public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException {
// 解析注解,得到属性的属性
// 注解在谁头上就用谁来获取: 注解在成员方法上,使用Method来获取
Class<?> cls = Class.forName("com.itzhuzhu.Book");
Method m1 = cls.getMethod("sale");
// 获取所有的注解
Annotation[] as = m1.getAnnotations();
for (Annotation a : as) {
System.out.println("a = " + a);
}
System.out.println("-------");
// 最好先判断,再获取
// boolean isAnnotationPresent(Class<Annotation> annotationClass) 判断是否有指定的注解
boolean b = m1.isAnnotationPresent(BookAnno.class);
System.out.println("b = " + b);
if (b) {
// T getAnnotation(Class<T> annotationClass) 获取指定类型的注解
BookAnno an = m1.getAnnotation(BookAnno.class);
System.out.println(an.name()); // 西游记
System.out.println(an.price()); // 9.9
} else {
System.out.println("没有这个注解");
}
}