注解
注解的概念,作用
- 什么是“注解”:JDK1.5提出“注解”。在我们编写代码的时候,使用@Override,@FactionalInterface,@Test(JUnit),这些注解都是写在“源码”中。作为一个“标记”,告诉“注解解析器”怎样编译、运行下面的代码。
- 告诉编译期中的“注解解析器”下面的代码应该怎样编译
- 使用“注解解析器”来加载有“注解”的代码,根据注解的使用,来决定怎样执行下面的代码
- 实现注解的两个元素:
- 注解本身–我们可以自定义注解,注解本质上是一个“接口”。但定义时有自己的关键字@interface
- 注解解析器–一个类。如果“注解”时给编译器用的,就需要将“注解解析器”随着编译器一起启动。否则这个“注解”就应该有一个单独的“注解解析器”来单独启动,加载使用了注解的类,来决定怎样去执行。
自定义注解的基本格式:
- 我们可以自定义注解:
语法:public @interface 注解名{
}
- 示例代码:
public @interface MyTest {
}
//使用这个注解:
import org.junit.Test;
@MyTest
public class Student {
@MyTest
private String name;
@Test
@MyTest
public void show(){
System.out.println("show()...");
}
}
- 这个注解有两个问题:
- 我们的注解可以放在一个类的任意位置—而@Test注解只能用在“方法”上
- 我们的注解没有任何作用—因为没有注解解析器。
这两个问题全部由“元注解”解决!!!
元注解
元注解:它也是一个注解,是JDK中定义好的,元注解只用在“注解的定义上”,它可以约束新注解:
- 使用的位置
- 生命周期
使用位置:@Target元注解
ElementType.METHOD是@Target注解的“属性”,如果像约束新注解只能用在:成员方法上。@Target(ElementType.METHOD) public @interface MyTest{ }
它的可选有:- ElementType.TYPE:类,接口
- ElementType.FIELD:成员变量
- ElementType.METHOD:成员方法
- ElementType.PARAMETER:方法参数
- ElementType.CONSRUCTOR:构造方法
- ElementType.LOCAL_VARIABLE:局部变量
生命周期:@Retention元注释
例如:@Retention(RetentionPolicy,SOURCE),约束新注释只存在于“源码中”,不会被编译到class中
RetentionPolicy.SOURCE是@Rentention元注释的“属性”,它的可选值:- RetentionPolicy.SOURCE:注释只存在于“源码”中,例如:@Override
- RetentionPolicy.CLASS:注释可以存在于“源码”,“class”文件中
- RetentionPolicy.RUNTIME:注释可以存在于“源码”,“class文件”,运行时会被加载到内存。例如:@Test
代码演示:
自定义注解
@Target({ElementType.METHOD})//1.约束新注解:使用的位置
@Retention(RetentionPolicy.RUNTIME)//2.约束新注解:生命周期
public @interface MyTest {
}
代码图解
解析注解
- 这里我们单独编写一个“类”,包含main()方法,作为我们自定义的注解@MyTest注解的“注解解析器”,来模拟JUnit的@Test的注解解析器。
- 在这个“注解解析器”中,需要使用“反射”技术
- 步骤:
- 编写一个注解
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface MyTest {
}
2. 使用这个注解:
public class Student {
@MyTest
public void show1(){
System.out.println("show1");
}
@MyTest
public void show2(){
System.out.println("show2");
}
}
3. 注解解析器:
public class Demo09 {
public static void main(String[] args) throws Exception {
//1.获取Student的Class对象
Class stuClass = Class.forName("com.itheima.demo09_注解解析器.Student");
//2.创建它的对象
Object o = stuClass.getConstructor().newInstance();
//3.获取它内部所有的"公有"方法
Method[] ms = stuClass.getMethods();
//4.遍历这些方法
for (Method m : ms) {
//5.判断这个方法上是否使用了@MyTest注解
if(m.isAnnotationPresent(MyTest.class)){
//6.执行此方法
m.invoke(o);
}
}
}
}
定义包含属性的注释:
- 注释中可以定义属性:
格式:
public @interface MyTest{
//属性格式:
数据类型名 属性名() [default 值];
} - 注释中属性的作用:可以更详细的对注释进行设置。
- 其它说明:
- 属性的“数据类型”可以是以下几种类型:
- 所有的“基本数据类型”(四类八种)
- String类型
- Class类型
- 枚举类型
- 注解类型
- 以上类型的“数组”类型
注意:没有“包装类”类型
- 如果“注释”中只有一个属性,而且属性名叫“value”
public @interface MyTest{
int value;
}
在使用时:可以简写也可以完整写
- 属性的“数据类型”可以是以下几种类型:
public class Student {
@MyTest(1)//可以简化写为:@MyTest(1),也可以完整写:@MyTest(value = 1)
public void show2(){
System.out.println("show2() index = 1");
}
@MyTest(2)
public void show1(){
System.out.println("show1() index = 2");
}
public void test1(){
System.out.println("test1()");
}
@MyTest(3)
public void test2(){
System.out.println("test2() index = 3");
}
}
代码演示:
测试类:
package com.itheima.demo10_定义带属性的注解;
import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.Comparator;
public class Demo10 {
public static void main(String[] args) throws Exception {
//1.获取Class
Class stuClass = Class.forName("com.itheima.demo10_定义带属性的注解.Student");
//2.创建对象
Object o = stuClass.getConstructor().newInstance();
//3.获取所有"公有"成员方法
Method[] ms = stuClass.getMethods();
//4.对方法进行排序,根据@MyTest注解的index属性值排序
Arrays.sort(ms, new Comparator<Method>() {
@Override
public int compare(Method o1, Method o2) {
//1.判断两个方法上都使用的@MyTest注解
if(o1.isAnnotationPresent(MyTest.class) &&
o2.isAnnotationPresent(MyTest.class)){
//2.获取MyTest注解的index值
int index1 = o1.getAnnotation(MyTest.class).value();
int index2 = o2.getAnnotation(MyTest.class).value();
//3.用这两个index值做比较
return index2 - index1;
}
return 0;
}
});
//5.遍历数组
for (Method m : ms) {
if (m.isAnnotationPresent(MyTest.class)) {
//执行此方法
m.invoke(o);
}
}
}
}
注解类:
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 {
//定义一个属性index
int value() ;
}
Student类:
public class Student {
@MyTest(1)
public void show2(){
System.out.println("show2() index = 1");
}
@MyTest(2)
public void show1(){
System.out.println("show1() index = 2");
}
public void test1(){
System.out.println("test1()");
}
@MyTest(3)
public void test2(){
System.out.println("test2() index = 3");
}
}
代码图解
版权声明:本文为weixin_45144691原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。