文章目录
- 简介
- Java内置注解
- 自定义注解
- 注解属性
- 元注解
- Target注解
- Retention注解
- 自定义注解用于配置文件
简介
注解(Annotation)又称标注,是 JDK5.0 引入的一种注释机制。Java 语言中的类、方法、变量、参数和包等都可以被标注。和Javadoc不同,Java注解可以通过反射获取注解内容。
在编译器生成类文件时,注解可以被嵌入到字节码中。Java虚拟机可以保留注解内容,在运行时可以获取到注解内容 。
Java内置注解
Java给我们提供了一些注解,以下是部分举例
//@Override:检查该方法是否是重写方法,如果不是会报错
//@SuppressWarnings:指示编译器去忽略注解中声明的警告
@SuppressWarnings(value = "all")
public class MyThread implements Runnable {
@Override
public void run() {
}
}
//@Deprecated:标记过时方法、类等。如果使用该方法,会报编译警告。
@Deprecated
public class Student {
}
除此之外,Java中还有其他注解,在此不举例说明
自定义注解
Annotation是一个接口,而对于自定义注解要实现该接口
自定义注释的写法如下:
public @interface MyAnnotation {
}
我们将该".java"文件在控制台编译成字节码,再将".class"文件通过"javap"指令反编译得到:
public interface task1.MyAnnotation extends java.lang.annotation.Annotation {}
以此可以证明自定义注解实现了Annotation接口。
使用自定义注解
@MyAnnotation()
public class Student {
}
注解属性
注解中的抽象方法被称为属性,如果注解中存在属性,在使用注解时需要给属性赋值,除非属性有默认值
public @interface MyAnnotation {
//返回值类型:基本数据类型、String、枚举、Class、Annotation以及以上类型的一维数组
String name();
//给属性定义默认值
int num() default 100;
String[] strings();
}
//因为num属性有默认值,可以不赋值
@MyAnnotation(name="abc",strings={"aaa","bbb","ccc"})
public class Student {
}
注解中的属性名为value的属性比较特殊,如果只有该属性需要被赋值,那么在赋值时可以不声明属性名。
public @interface MyAnnotation {
String value();
int num() default 100;
}
@MyAnnotation("aaa")
public class Student {
}
元注解
元注解就是用于标注注解类型的注解
Target注解
@Target:指示注解类型所适用的程序元素的种类,用于限定注解的适用范围
在Java的帮助文档中可以查询该注解,该注解只有一个属性value,返回值类型为ElementType[ ],是一个枚举类型的数组,代表元素的种类的数组。
//该注解只能用于标注字段和方法
@Target({ElementType.FIELD,ElementType.METHOD})
public @interface MyAnnotation {
String value();
int num() default 100;
String[] strings();
}
ElementType的枚举常量摘要:
ANNOTATION_TYPE:注释类型声明
CONSTRUCTOR:构造方法声明
FIELD:字段声明(包括枚举常量)
LOCAL_VARIABLE:局部变量声明
METHOD:方法声明
PACKAGE:包声明
PARAMETER:参数声明
TYPE:类、接口(包括注释类型)或枚举声明
Retention注解
@Retention:指示注解类型的注解要保留多久
该注解也只有一个属性value,返回值类型为RetentionPolicy枚举类型。
//该注解保留至运行期
@Retention(RetentionPolicy.RUNTIME)
public @interface MyAnnotation {
String value();
int num() default 100;
String[] strings();
}
RetentionPolicy的枚举常量摘要
CLASS:编译器将把注解记录在类文件中,但在运行时VM不需要保留注解。 即保留在代码和字节码文件中
RUNTIME:编译器将把注解记录在类文件中,在运行时VM将保留注解,因此可以反射性地读取。 既保留在运行期
SOURCE:编译器要丢弃的注解。即保留在编译器,在字节码文件中会被删除
自定义注解用于配置文件
使用注解代替JDBC配置文件
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface JDBCAnnotation {
String className() default "com.mysql.jdbc.Driver";
String url();
String username();
String password();
}
import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
public class JDBCUtils {
private JDBCUtils(){}
@JDBCAnnotation(url = "jdbc:mysql://localhost:3306/mydb",username = "root",password = "123")
public static Connection getConnection() throws NoSuchMethodException, ClassNotFoundException, SQLException {
//通过反射机制来读取注解中的数据
Class<JDBCUtils> jdbcUtilsClass = JDBCUtils.class;
Method method = jdbcUtilsClass.getMethod("getConnection");
Connection conn=null;
//判断方法上有没有JDBCAnnotation注解
if(method.isAnnotationPresent(JDBCAnnotation.class)){
//获取注解对象
Annotation annotation = method.getAnnotation(JDBCAnnotation.class);
String className = ((JDBCAnnotation) annotation).className();
String url = ((JDBCAnnotation) annotation).url();
String username = ((JDBCAnnotation) annotation).username();
String password = ((JDBCAnnotation) annotation).password();
Class.forName(className);
conn = DriverManager.getConnection(url, username, password);
}
return conn;
}
}