什么是注解
注释和注解
- 注释:用文字描述程序,写给程序员看的
- 注解:说明程序,给计算机看的
定义:
注解(Annotation),也叫元数据。一种用代码级别的说明。它是JDK1.5及以后的版本引入的一个特性,与类、接口、枚举是在同一个层次。他可以声明在包、类、字段、方法、局部变量、方法参数等的签名,用来对这些元素进行说明
概念描述
- JDK1.5之后的新特性
- 说明程序的
- 使用注解:@注解名称
作用分类
- 编写文档:通过代码里标识的注解生成文档(Javadoc文档)
- 代码分析:通过注解里标识的注解对代码进行分析(使用反射)
- 编译检查:通过代码里标识的注解让编译器能过实现基本的编译检查(Override)
JDK内置注解
最常见的几种注解
- @Override:检测被该注解标注的方法是否继承自父类
- @Deprecated:该注解表示的内容表示已经过时了,不推荐使用
- @SuppressWarnings :压制警告
常见注解的使用
@Override:检测被该注解标注的方法是否继承自父类
由上面的代码可以看见
父类里面没有say方法,加上@Override就会报错
说明父类里面没有此方法可以重写
父类里面有的方法,就会正常显示
@Deprecated:该注解表示的内容表示已经过时了,不推荐使用
我们这里拿诺基亚举例
不管是以前的诺基亚还是现在的诺基亚,他都能打电话
但是官方还是推荐使用现在的诺基亚
不影响以前的诺基亚功能
想用它打电话照样还是能打
@SuppressWarnings :压制警告
有时候我们写代码的时候看到一些警告信息非常的不爽
这个时候使用注解可以压制他
加上@SuppressWarnings 就可以压制警告了
里面传参数 “all” 表示压制所有的警告
也可以压制一些局部的警告,例如从未被使用警告
通常我们可以吧压制警告写在类上面
这样就可以压制所有的警告了
自定义注解
本质
本质:注解本质上就是一个接口,改接口继承了Annotation接口
我们对一个注解类进行反编译后得到的是
原java代码
public @interface MyAnno {}
反编译后
public interface MyAnno extends java.lang.annotation.Annotation {}
格式
public @interface 注解名称{
int value();//属性名 可以不写
}
属性
要求
1.属性的返回值有下列取值
- 基本数据类型(8种)
- String
- 枚举
- 注解
- 以上类型的数组
2.定义了属性,在使用的时候给属性赋值
- 如果定义属性时候,使用default关键字给属性默认初始化值
- 如果只有一个属性需要赋值,并且属性的名称是value,则value可以省略,直接定义值即可
- 数组赋值时,值使用{}包裹,如果数组只有一个值 则{}可以省略
元注解:用于描述注解的注解
-
@Target:描述注解能够作用的位置
ElementType取值- TYPE:类,接口(包括注释类型),或枚举声明
- FIELD:字段声明(包括枚举常数)
- METHOD:方法声明
- PARAMETER:形式参数的声明
- CONSTRUCTOR:构造函数声明
- LOCAL_VARIABLE:局部变量声明
- ANNOTATION_TYPE:注释类型声明
- PACKAGE:包声明
-
@Retention:描述注解被保留的阶段
- RetentionPolicy.SOURCE :只在源码中保留,编译后注解消失
- RetentionPolicy.CLASS :可以被编译,但是运行会被jvm舍去
- RetentionPolicy.RUNTIME:可以被jvm保留到程序执行
-
@Documented:描述注解是否可以被抽取到javadoc文档中
-
@Inherited:描述你定义的注解是否被描述的类的子类继承,如果加上此注解,那么被定义注解描述的类的子类默认也会加上你定义的注解
使用
下面通过一些代码来演示注解的使用
注解类代码
//一些元注解
//@Target(ElementType.METHOD)//描述注解作用在方法中
@Target({ElementType.METHOD,ElementType.TYPE})//描述注解作用在方法和类中
@Retention(RetentionPolicy.RUNTIME)//描述注解可以保留到程序执行
public @interface MyAnno {
//字段
int age();
String name();
char sex() default('男');//默认是男
}
使用注解类
@MyAnno(name = "类",age = 0)//ElementType.TYPE 可以作用在类上
public class AnnDemo1 {
//sex使用默认的 ‘男’
@MyAnno(name="张三",age=25)//ElementType.METHOD 作用在方法上
public void say1(){
}
@MyAnno(name="小七",age=23,sex='女')
public void say2(){
}
}
解析注解
这里使用到了反射
如果不会反射的话
点击这里进入 [Java核心技术]-反射技术 快速学习
//配置写在这里
@MyAnno(name = "一个测试类",age = 25)
public class AnnDemo1 {
public static void main(String[] args) {
//获取本类的class对象
Class<AnnDemo1> annDemo1Class = AnnDemo1.class;
//注解也是个接口,可以直接调用里面的抽象方法(属性)
MyAnno an = annDemo1Class.getAnnotation(MyAnno.class);
int age = an.age();
String name = an.name();
char sex = an.sex();
System.out.println("age:"+age +" name:"+name+" sex:"+sex);
//age:25 name:一个测试类 sex:男
}
}