关于JAVA中源码级注解的编写及使用

一、注解简介: 1.1.什么是“注解”:

​ 在我们编写代码时,一定看到过这样的代码:

class Student { private String name; @Override public String toString(String str) {//编译错误! return "Student name = " + name; } }

​ 其中的@Override,就是一个“注解”,@Override一般出现在重写equals()或者toString()方法的上边,意思是告诉编译器:下边的代码是重写父类方法的。这时编译器会按照“重写”的语法严格检查下面的方法,如果不符合重写语法,将会编译错误。

​ "注解"作为一种“标记”,被写在源码中,不会改变程序的执行流程。它通常由“注解解析工具”来解析,而“注解解析器”可以随Java编译器启动,也可以独立启动,来解析注解,并以此可以做一些事情。

1.2.注解的分类: 源码注解:

​ 注解只在源码中,编译成class文件后就不存在了。

编译时注解:

​ 注解在源码和.class文件中都存在(如:JDK内置系统注解)

运行时注解:

​ 在运行阶段还起作用,甚至会影响运行逻辑的注解(如:JUnit的@Test)

1.3.注解的作用

​ 注解的作用非常广泛,注解可以被用在类、属性、构造方法、成员方法、局部变量等位置,用于对这些元素进行说明。由“注解解析工具”解析后,可以生成文档、进行代码分析、编译检查等。
​ 本例将会实现一个用作"编译检查“的注解,以及一个"注解解析器"。"注解解析器"将会随着javac编译器一同启动来对使用了注解的类进行编译,并检查类名、字段名、方法名是否以大写、小写字符开头,如果违反了规则,编译时将会报错。

二、自定义注解: 2.1.定义注解的基本语法

​ “注解”本质上是一个“类”,我们可以根据自己的需要定义自己的注解。
​ 定义注解的语法很简单:

public @interface CheckWord{ ... }

​ "注解”编译后会生成.class文件。但这是一个非常简单的注解,它可以被用在任何位置,而且编译器遇到这种注解也不做任何事情。例如:

@CheckWord public class Student { @CheckWord public Student() { } @CheckWord private String name; @CheckWord public void study() { } }

下面我们先使用“元注解”来规定这个注解可以被用在哪里。

2.2.元注解

​ “元注解”也是一种“注解”,它是已经实现好的。必须用在“注解”的定义上,它可以规定注解可以用在哪里,以及可以存在于源码中,或者class中,或者运行时。
常用的“元注解”有两个:
​ 1).@Target : 规定注解可以用在哪里。常用的取值被定义在枚举java.lang.annotation.ElementType中:
​ ElementType.TYPE:类和接口上
​ ElementType.FIELD: 用在成员变量上
​ ElementType.METHOD: 用在方法上
​ ElementType.PARAMETER: 用在参数上
​ ElementType.CONSTRUCTOR: 用在构造方法上
​ ElementType.LOCAL_VARIABLE: 用在局部变量上
​ 2).@Retention : 规定注解可以存在于哪里。常用的取值被定义在枚举java.lang.annotation.RetentionPolicy中:
​ RetentionPolicy.SOURCE: 规定注解只存在于Java源代码中, 编译生成的字节码文件中就不存在了。
​ RetentionPolicy.CLASS: 规定注解存在于Java源代码、 编译以后的字节码文件中, 但JVM运行时,不会被加载到内存。
​ RetentionPolicy.RUNTIME: 规定注解存在于Java源代码中、 编译以后的字节码文件中、 运行时内存中, 程序可以通过反射获取该注解。
​ 例如:修改我们的注解,规定它只能用在"类","字段",“方法”上,并且可以存在于“源码中”:

import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; @Target({ElementType.TYPE, ElementType.FIELD, ElementType.METHOD}) @Retention(RetentionPolicy.SOURCE) public @interface CheckWord { }

​ 如果再编译之前的Student类,会发现用在"构造方法"上的@CheckWord会编译错误,因为我们规定了它只能用在"类","字段","方法"上。

2.3.定义注解的属性:

1.“注解”中可以定义一些属性,“注解解析器”可以根据“属性”的不同,分别做不同的事情。

​ 例如@Target注解中的ElementType.TYPE就是此注解的一个属性,它是一个"枚举"类型。
​ 下面让我们来看看怎样定义属性,然后再解析这些属性。
​ 注解中定义属性的语法:数据类型 属性名() [deafult 值];
​ 1.其中“数据类型”可以是:
​ 1).所有基本类型;
​ 2).String;
​ 3).Class;
​ 4).枚举;
​ 5).注解;
​ 6).以上任一类型的数组
​ 2.属性名():属性名可以自由设定,要遵循Java标识符的命名规则;其中的一对()是必须的。
​ 3.[default 值]:为此属性设置的默认值。
2.本例中由于只检查大小写,为了规范取值,所以定义一个"枚举"类型的属性。
​ 1).先定义枚举:

public enum StartsWith { UPPERCASE, LOWERCASE }

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/zyfypj.html