文章目录

  • 简介
  • 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;
    }
}