Java 定义了一套注解,共有 7 个,3 个在 java.lang 中,剩下 4 个在 java.lang.annotation 中。
作用在其他注解的注解(或者说元注解
)是:
从 Java 7 开始,额外添加了 3 个注解:
下面介绍几个常用的注解
标识这个注解怎么保存,是只在代码中,还是编入class文件中,或者是在运行时可以通过反射访问。
@Retention(RetentionPolicy.RUNTIME) //source < class < runtime(runtime级别最高)
标记这个注解应该是哪种 Java 成员使用。
@Target(ElementType.CONSTRUCTOR)//在构造器上声明
用括号{}
,写多个值,其实是传入一个ElementType[] value()
数组:
@Target({ElementType.CONSTRUCTOR,ElementType.METHOD,ElementType.TYPE})//表示可以在构造器,方法和类上使用
也可以通过导包进行简写:
import static java.lang.annotation.ElementType.*;
@Target({CONSTRUCTOR,METHOD,TYPE})
源码定义:
@Target({TYPE, FIELD, METHOD, PARAMETER, CONSTRUCTOR, LOCAL_VARIABLE})
@Retention(RetentionPolicy.SOURCE)
public @interface SuppressWarnings {
String[] value();
}
SuppressWarnings
的作用是,让编译器对它所标注的内容
的某些警告保持静默
。例如,"@SuppressWarnings(value={“deprecation”, “unchecked”})" 表示对"它所标注的内容"中的 "SuppressWarnings 不再建议使用警告"和"未检查的转换时的警告"保持沉默。 函数式接口注解,这个是 Java 1.8 版本引入的新特性。函数式编程很火,所以 Java 8 也及时添加了这个特性。被标记为函数式接口的方法可以使用Lambda表达式。例如我们经常用的Runnable接口
我们可以定义一个DbConnection
的注解,用来代替数据库连接配置文件db.properties
注意:所有的注解都必须要带两个注解:@Retention()
、@Target()
/**
* DbHelper 连接注解
*/
@Retention(RetentionPolicy.RUNTIME)//表示在运行时有,这样在源码,字节码和运行期都有
@Target(ElementType.METHOD)//作用在方法上面
public @interface DbConnection {
public String userName();
public String password();
public String driverName() default "com.mysql.cj.jdbc.Driver";
public String url() default "jdbc:mysql://localhost:3306/iot?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=Asia/Shanghai";
}
每一个属性对应的是一个方法,方法有返回值:
public String userName();
也可以给属性添加默认值,在使用注解时就可以不用填了
public String driverName() default "com.mysql.cj.jdbc.Driver";
然后我们可以在方法上面进行使用这个注解:
@DbConnection(userName = "root",password = "123456")
private Connection getConn(){
}
但此时是没有用的,因为还没有配置注解解析器
注解解析器其实就是利用反射将反射对象里的每个方法拿到,在根据拿到的方法拿到上面的注解,再对注解进行解析
注解解析器:
@DbConnection(userName = "root",password = "123456")
public Connection getConn() throws Exception{
//1. 取出这个方法对应的类的对象的反射实例
Method method = this.getClass().getMethod("getConn");
//取上面的注解
Annotation[] ans = method.getDeclaredAnnotations();
//可能有多个注解,循环取值
for(Annotation an : ans){
if(an instanceof DbConnection){
//类型转换
DbConnection dbConn = (DbConnection) an;
//取到注解里面的值
String userName = dbConn.userName();
String password = dbConn.password();
String url = dbConn.url();
String driverName = dbConn.driverName();
//注册驱动
Class.forName(driverName);
//获得连接
Connection conn = DriverManager.getConnection(url, userName, password);
return conn;
}
}
return null;
}
测试:
public static void main(String[] args) throws Exception {
DbHelper dbHelper = new DbHelper();
Connection conn = dbHelper.getConn();
System.out.println(conn);
}
下一节笔者会模仿一个现在非常优秀的测试框架Junit
用注解进行简单实现
注解学习二、使用注解仿写junit测试框架