前言
在你立足处深挖下去,就会有泉水涌出!别管蒙昧者们叫嚷:“下边永远是地狱!”
博客主页:KC老衲爱尼姑的博客主页
博主的github,平常所写代码皆在于此
共勉:talk is cheap, show me the code
作者是爪哇岛的新手,水平很有限,如果发现错误,一定要及时告知作者哦!感谢感谢!
文章目录
- 注解
- 概述
- 注解的作用
- 元注解
- 注解的解析
- 模拟Junit中的@Test
注解
概述
Java注解是Java5引入的一种注释解释,又称之为标注。Java中的类,构造器,方法,成员变量,参数等都可以被注解进行标注。我们可以将注解理解为标签,标签可以上的内容可以自由的定义,它是对人和事物属性的评价。这就如商品上的价格标签,图书馆中的书本编码标签,B站上游戏分区标签等。
注解的作用
对Java中类,方法,成员变量做标记,然后进行特殊处理,至于到底进行何种处理由具体业务决定。比如说:JUnit框架中,标注了注解为@Test的方法就可以被当成测试方法执行,而没有标记的就不能打算当初当成测试方法执行。
特殊属性
- value属性,如果只有一个value属性的情况下,使用value属性的时候可以省略value名称不写。
- 但是如果有多个属性,并且属性没有默认值,那么value名称不能省略。
自定义注解格式
public @interface 注解名称 {
public 属性类型 属性名() default 默认值;
}
代码示例
public @interface MyDemo {String value();String name();boolean flag() default true;String [] str();
}
元注解
元注解就是注解的注解,注解的标签。
常用的元注解
- @Target: 约束自定义注解只能在哪些地方使用
- @Retention:申明注解的生命周期
@Target中可使用的值定义在枚举类ElementType中,常用值如下:
- TYPE,类
- 接口 FIELD,
- 成员变量METHOD,
- 成员方法PARAMETER,
- 方法参数CONSTRUCTOR,
- 构造器LOCAL_VARIABLE
- 局部变量
@Retention中可使用的值定义在枚举类ElementType中,常用值如下:
- SOURCE: 注解只作用在源码阶段,生成的字节码文件中不存在
- CLASS: 注解作用在源码阶段,字节码文件阶段,运行阶段不存在,默认值.
- RUNTIME:注解作用在源码阶段,字节码文件阶段,运行阶段(开发常用)
注解的解析
示例代码
@Target({ElementType.TYPE,ElementType.METHOD})// 当前被修饰的注解只能用在类上,方法上。
@Retention(RetentionPolicy.RUNTIME)// 控制下面的注解一直保留到运行时
public @interface MyTest {
}
MyTest的使用
@MyTest
public class AnnotationTest {
// @MyTest
// private String name;@MyTest@MyDemo(value = "Annotation",name="张三",str={"java","C++"})public static void test() {System.out.println("Hello World");}public static void main(String[] args) {test();}
}
如果把@MyTest修饰在成员变量上就会报错—>java: 注释类型不适用于该类型的声明
注解的解析
注解的操作中经常需要解析,注解的解析就是判断是否存下注解,存在注解就解析出内容。
与注解解析相关的接口
- Annotation: 注解的顶级接口,注解都是Annotation类型的对象
- AnnotatedElement:该接口定义了与注解解析相关的解析方法
相关API如下
方法 | 说明 |
---|---|
Annotation[] getDeclaredAnnotations() | 获得当前对象上使用的所有注解,返回注解数组。 |
T getDeclaredAnnotation(Class annotationClass) | 根据注解类型获得对应注解对象 |
boolean isAnnotationPresent(Class annotationClass) | 判断当前对象是否使用了指定的注解,如果使用了则返回true,否则false |
所有的类成分Class, Method , Field , Constructor,都实现了AnnotatedElement接口他们都拥有解析注解的能力。
注解解析案例
首先定义一个MyTest2注解
@Target({ElementType.TYPE,ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface MyTest2 {String value();String name();boolean flag() default true;String [] str();
}
在Demo类和方法上使用
@MyTest2(value = "大小姐",name ="林黛玉",str={"java","C++"})
public class Demo {@MyTest2(value = "小小姐",name ="薛宝钗",str={"java","Python"})public void test() {}}
解析类上的注解
public class AnnotationTest2 {public static void main(String[] args) {//1.得到class对象Class<Demo> demoClass = Demo.class;//2.判断类上是否包含注解if (demoClass.isAnnotationPresent(MyTest2.class)) {MyTest2 myTest2 = demoClass.getDeclaredAnnotation(MyTest2.class);System.out.println(myTest2.value());System.out.println(myTest2.name());System.out.println(myTest2.flag());System.out.println(Arrays.toString(myTest2.str()));}}
}
运行结果:
解析方法上的注解
public class AnnotationTest3 {public static void main(String[] args) throws NoSuchMethodException {//1.得到class对象Class<Demo> demoClass = Demo.class;Method test = demoClass.getDeclaredMethod("test");//2.判断方法对象上是否包含注解if (test.isAnnotationPresent(MyTest2.class)) {MyTest2 myTest2 = test.getDeclaredAnnotation(MyTest2.class);System.out.println(myTest2.value());System.out.println(myTest2.name());System.out.println(myTest2.flag());System.out.println(Arrays.toString(myTest2.str()));}}
}
运行结果:
模拟Junit中的@Test
我们定义若干个方法,只要加了MyTest注解,就可以在启动时被触发执行
分析
- 定义一个自定义注解MyTest,只能注解方法,存活范围是一直都在。
- 定义若干个方法。只要有@MyTest注解的方法就能在启动时被触发执行,没有这个注解的方法不能执行。
示例代码
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;public class TestDemo {@MyTestpublic void test1() {System.out.println("test1");}@MyTestpublic void test2() {System.out.println("test2");}@MyTestpublic void test3() {System.out.println("test3");}@MyTestpublic void test4() {System.out.println("test4");}public static void main(String[] args) throws InvocationTargetException, IllegalAccessException {TestDemo t = new TestDemo();//启动程序//1.得到TestDemo对象Class<TestDemo> testDemoClass = TestDemo.class;//提取类中的方法Method[] declaredMethods = testDemoClass.getDeclaredMethods();//触发方法for (Method method : declaredMethods) {if (method.isAnnotationPresent(MyTest.class)) {method.invoke(t);}}}
}
运行结果:
各位看官如果觉得文章写得不错,点赞评论关注走一波!谢谢啦!。