JAVA程序进阶——注解
注解:说明程序。给计算机看的
注释:用于文件描述程序 给程序员看的
- 作用
- 编写文档:通过代码的标识的注解生成文档
- 代码分析:通过标识的注解对代码进行分析【使用反射】
- 编译检查:通过代码里标识的注解能够实现基本的编译检查
一、系统部分自带注解
1. @Override
检测被该注解标注的方法是否是继承自父类(接口)的
@Override
public String toString() {
return super.toString();
}
2. @Deprecated
该注解标准的内容,表示已过时
@Deprecated
public int addMethod(int a){
return a+a;
}//调用被执行过时的方法时,该方法名会被划掉
3.@SuppressWarnings
压制警告
@SuppressWarnings("all")//一般写在类上会压制类里的所有警告包括过时警告
public class addTest {}
二、自定义注解
1. 语法
注解本质上就是一个接口 改接口继承自Annotation接口
元注解//用于描述注解的注解
public @interface 注解名称 {
}
例
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD})
public @interface Before {
}
2. 注解属性
注解属性就是接口的抽象方法
抽象方法的返回值 不可以是void 可以是:基本类型,String,枚举,注解,以上类型的数组
public @interface Demo {
String name();//定义方法后需要在 注解里进行赋值
String gender() default "男";//在定义方法后 设置默认值就可以不用在注解中进行赋值
}
@Demo(name = "测试")//需要对name进行赋值
public void show()
{
System.out.println("测试注解");
}
例
public @interface SuppressWarnings {
String[] value();
//数组赋值时候,应该使用{}包裹,如果属性只有一个值可以省略{}
}
@SuppressWarnings("all")//{}被省略
//如果注解只有一个属性需要赋值,并且值是value,那么就可以省略 署名名称直接赋值
public void show()
{
System.out.println("压制所有警告");
}
3. 元注解
@Target
描述注解能够作用的位置
public @interface Target {
ElementType[] value();//说明内部传入的参数是枚举类型
}
枚举类型可以传入的参数
-
TYPE:可以作用于类上
-
METHOD:可以作用于方法上
-
FIELD:可以作用于变量上
-
CONSTRUCTOR: 可以作用于构造器上
-
ANNOTATION_TYPE:可以作用于注解上
@Target({ElementType.TYPE,ElementType.FIELD,ElementType.METHOD})
public @interface Demo {
String name();
String gender() default "男";
}
@Retention
描述注解被保留的阶段
public @interface Retention {
RetentionPolicy value();//说明内部传入的参数是枚举类型
}
RetentionPolicy可以传入的参数
- SOURCE :可以作用于资源阶段
- CLASS:可以作用于类阶段
- RUNTIME:可以作用于运行时阶段,会被保留到class字节码文件中被JVM读取到(自定义常用阶段)
@Retention(RetentionPolicy.RUNTIME)
public @interface Retention {
RetentionPolicy value();
}
@Documented
描述注解是否被抽取到api文档中
@Inherited
描述注解是否被子类继承
@Target(ElementType.ANNOTATION_TYPE)//该元注解只能作用于注解上
public @interface Inherited {
}
三、使用(解析)自定义注解
以创建数据库链接为例
1.自定义注解
@Retention(RetentionPolicy.RUNTIME)//作用是可以将注解保留在字节码文件中,用于以后反射取值
@Target(ElementType.TYPE)//只能作用于类中
public @interface Pro {
//创建几个属性(抽象方法)
String driver();
String url();
String username();
String password ();
}
2.在该类中添加自定义的注解并给属性赋值
@Pro(
driver = "com.mysql.cj.jdbc.Driver",
url="jdbc:mysql://localhost:3306/db1useUnicode=true&character=utf8&useSSL=false&serverTimezone=UTC",
username="root",password = "123456")
public class JdbcUtils {
public static String driver=null;
public static String url=null;
public static String username=null;
public static String password=null;
}
3.解析自定义注解,获得属性的值
Class jdbcUtilsClass = JdbcUtils.class;//获得该类的字节码文件
Pro pro = (Pro) jdbcUtilsClass.getAnnotation(Pro.class);//通过字节码文件得到封装的注解类,得到的注解是Pro注解
//getAnnotation的返回值是Annotation但是Pro注解继承了Annotation
//该方法实现了Pro注解下的属性(抽象方法)
try {
driver=pro.driver();//调用方法得到值
url=pro.url();
username=pro.username();
password= pro.password();
Class.forName(driver);
} catch (Exception e) {
e.printStackTrace();
}