注解的概述:
Java注解(Annotation)又称Java标注,是JDK5引入的一种注释机制。
Java语言中的类、构造器、方法、成员变量、参数等都可以被注解进行标注。
作用:
对Java中类、方法、成员变量做标记,然后进行特殊处理,至于到底做何种处理由业务需求来决定。
例如。JUnit框架中,标记了注解@Test的方法就可以被当成测试方法执行,而没有标记的就不能当成测试方法执行。
目录
自定义注解:
//格式:
Public @interface 注解名称{
public 属性类型 属性名() default 默认值;
}
//自定义一个注解
public @interface MyBook {
//支持很多类型
String name();
String [] authors();
double price();
}
@MyBook(name = "<遇安的博客>",authors = "遇安",price = 9.9)//可以使用刚刚定义的注解,里面需要填上它所有的属性值
//可以标记类
public class 注解 {
//可以标记构造器
@MyBook(name = "<遇安的博客>",authors = "遇安",price = 9.9)
private 注解(){
}
//可以标记方法
@MyBook(name = "<遇安的博客>",authors = "遇安",price = 9.9)
public static void main(String[] args) {
//局部变量也可以标记
@MyBook(name = "<遇安的博客>",authors = "遇安",price = 9.9)
int age=18;
}
}
特殊属性:
value属性,如果只有一个value属性的情况下,使用value属性的时候可以省略value名称不写
//自定义一个注解
public @interface Book {
String value();//特殊属性
}
//@Book(value = "/delete")//可以写上value属性名称
@Book("/delete")//也可以不写
public class 注解 {
public static void main(String[] args) {
}
}
但是如果有多个属性,且多个属性没有默认值,那么value名称是不能省略的,
省略便会报错。
//自定义一个注解
public @interface Book {
String value();//特殊属性
double price();
}
@Book(value = "/delete",price = 9.9)//当有多个属性且没有默认值的时候,不可以省略名称
public class 注解 {
public static void main(String[] args) {
}
}
当多个属性有默认值的时候,是可以省略名称的
//自定义一个注解
public @interface Book {
String value();//特殊属性
double price() default 9.9;
}
@Book("/delete")//当多个属性有默认值的时候,便可以省略名称
public class 注解 {
public static void main(String[] args) {
}
}
从这些案例可以看出,注解的每个属性都必须要给值,不给值便会出问题、报错。
元注解:
元注解就是注解注解的注解(写在注解上面的注解)
@Target:约束自定义注解只能在哪些地方使用。
import java.lang.annotation.ElementType;
import java.lang.annotation.Target;
//元注解
@Target({ElementType.FIELD,ElementType.METHOD})//规定可以注解成员变量和方法
public @interface MyText {
}
//@MyText//不能注解类
public class 注解 {
//可以注解成员变量
@MyText
private String name;
//可以注解方法
@MyText
public static void main(String[] args) {
}
}
@Retention:申明注解的生命周期。
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@Retention(RetentionPolicy.RUNTIME)//一直存在,在运行阶段这个注解也不消失
public @interface MyText {
}
注解的解析:
注解的操作中经常需要进行解析
注解的解析就是判断是否存在注解,存在注解就解析出内容。
- Annotation:注解的顶级接口,注解都是Annotation类型的对象
- AnnotatedElement:该接口定义了与注解解析相关的解析方法
- 所有的类成分Class、Method、Field、Constructor,都实现了AnnotatedElement接口,他们都拥有解析注解的能力。
注解的技巧:
注解在哪个成分上,我们就先那哪个成分对象。
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target({ElementType.TYPE,ElementType.METHOD})//限制只能注解到类和成员方法上
@Retention(RetentionPolicy.RUNTIME)//一直存在,在运行阶段这个注解也不消失
public @interface Book {
String value();
double price();
String [] author();
}
比如注解作用在类上,则要该类的Class对象,再来拿上面的注解
import org.junit.Test;
import java.lang.reflect.Method;
import java.util.Arrays;
//完成注解的解析
public class 注解 {
@Test
public void get(){
//得到类的对象
Class c=BookStore.class;
//判断这个类上面是否存在注解
if(c.isAnnotationPresent(Book.class)){
//直接获取该解析对象
Book book= (Book) c.getDeclaredAnnotation(Book.class);
System.out.println(book.value());
System.out.println(Arrays.toString(book.author()));
System.out.println(book.price());
//运行结果:
// <遇安的博客>
//[遇安]
//9.9
}
}
}
@Book(value = "<遇安的博客>",author = "遇安",price = 9.9)
class BookStore{
@Book(value = "<YuAn>",author = "遇安.",price = 9.99)
public void text(){
}
}
比如注解作用成员方法,则要获得该成员方法对应的Method对象,再来拿上面的注解
import org.junit.Test;
import java.lang.reflect.Method;
import java.util.Arrays;
//完成注解的解析
public class 注解 {
@Test
public void getMethod() throws NoSuchMethodException {
//先得到类的对象
Class c=BookStore.class;
//得到方法的对象
Method m= c.getDeclaredMethod("text");
//判断这个类上面是否存在注解
if(m.isAnnotationPresent(Book.class)){
//直接获取该解析对象
Book book= (Book) m.getDeclaredAnnotation(Book.class);
System.out.println(book.value());
System.out.println(Arrays.toString(book.author()));
System.out.println(book.price());
//运行结果:
// <YuAn>
//[遇安.]
//9.99
}
}
}
@Book(value = "<遇安的博客>",author = "遇安",price = 9.9)
class BookStore{
@Book(value = "<YuAn>",author = "遇安.",price = 9.99)
public void text(){
}
}
注解的应用:模拟junit框架
需求:
定义若干个方法,只要加了MyTest注解,就可以在启动时被触发执行
分析:
1、定义一个自定义注解MyTest,只能注解方法,存活范围是一直都在。
2、定义若干个方法,只要有@MyTest注解的方法就能在启动时被触发执行,没有这个注解的方法不能执行。
自定义注解类:
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 MyTest {
}
主类:
import java.lang.reflect.Method;
public class 注解的应用模拟junit框架 {
@MyTest
public void text1(){
System.out.println("text1");
}
public void text2(){
System.out.println("text2");
}
@MyTest
public void text3(){
System.out.println("text3");
}
//启动:有注解的才被调用
public static void main(String[] args) throws Exception {
注解的应用模拟junit框架 z=new 注解的应用模拟junit框架();
//获取类对象
Class c=注解的应用模拟junit框架.class;
//提取全部方法
Method [] methods=c.getDeclaredMethods();
//遍历方法,查看是否有@MyTese注解,有就运行
for (Method method:methods){
if(method.isAnnotationPresent(MyTest.class)){
//运行它
method.invoke(z);//由方法拿对象触发自己
}
}
}
//运行结果:
//text1
//text3
}