网站做app,设计logo网站免费横屏纯色,网页制作图片,网络推广做哪个网站比较好文章目录 第二十三章 注解1. 基本语法1.1 基本语法1.2 定义注解1.3 元注解 2. 编写注解处理器2.1 编写注解处理器2.2 注解元素2.3 默认值限制 3. 使用javac处理注解4. 基于注解的单元测试5. 本章小结 第二十三章 注解
注解#xff08;也被称为元数据#xff09;为我们在代码… 文章目录 第二十三章 注解1. 基本语法1.1 基本语法1.2 定义注解1.3 元注解 2. 编写注解处理器2.1 编写注解处理器2.2 注解元素2.3 默认值限制 3. 使用javac处理注解4. 基于注解的单元测试5. 本章小结 第二十三章 注解
注解也被称为元数据为我们在代码中添加信息提供了一种形式化的方式使我们可以在稍后的某个时刻更容易的使用这些数据。
通过使用注解你可以将元数据保存在 Java 源代码中。并拥有如下有下优势简单易读的代码编译器类型检查使用 annotation API 为自己的注解构造处理工具。
注解的语法十分简单主要是在现有语法中添加 符号。
1. 基本语法
1.1 基本语法
使用 Test 对 testExecute() 进行注解。该注解本身不做任何事情但是编译器要保证其类路径上有 Test 注解的定义。
package annotations;import onjava.atunit.Test;public class Testable {public void execute() {System.out.println(Executing..);}Testvoid testExecute() { execute(); }
}1.2 定义注解
注解的定义看起来很像接口的定义。事实上它们和其他 Java 接口一样也会被编译成 class 文件。
package onjava.atunit;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 Test {
}Target 定义你的注解可以应用在哪里例如是方法还是字段。 Retention 定义了注解在哪里可用在源代码中SOURCEclass文件CLASS中或者是在运行时RUNTIME。
不包含任何元素的注解称为标记注解marker annotation例如上例中的 Test 就是标记注解。
下面是一个简单的注解我们可以用它来追踪项目中的用例。
package annotations;import java.util.List;public class PasswordUtils {// 注解的元素在使用时表现为 名-值 对的形式并且需要放置在 UseCase 声明之后的括号内。UseCase(id 47, description Passwords must contain at least one numeric)public boolean validatePassword(String passwd) {return (passwd.matches(\\w*\\d\\w*));}UseCase(id 48)public String encryptPassword(String passwd) {return new StringBuilder(passwd).reverse().toString();}UseCase(id 49, description New passwords cant equal previously used ones)public boolean checkForNewPassword(ListString prevPasswords, String passwd) {return !prevPasswords.contains(passwd);}
}1.3 元注解
Java 语言中目前有 5 种标准注解 Override表示当前的方法定义将覆盖基类的方法。如果你不小心拼写错误或者方法签名被错误拼写的时候编译器就会发出错误提示。 Deprecated如果使用该注解的元素被调用编译器就会发出警告信息。 SuppressWarnings关闭不当的编译器警告信息。 SafeVarargs在 Java 7 中加入用于禁止对具有泛型varargs参数的方法或构造函数的调用方发出警告。 FunctionalInterfaceJava 8 中加入用于表示类型声明为函数式接口
以及 5 种元注解。元注解用于注解其他的注解
注解解释Target表示注解可以用于哪些地方。可能的 ElementType 参数包括CONSTRUCTOR构造器的声明FIELD字段声明包括 enum 实例LOCAL_VARIABLE局部变量声明METHOD方法声明PACKAGE包声明PARAMETER参数声明TYPE类、接口包括注解类型或者 enum 声明Retention表示注解信息保存的时长。可选的 RetentionPolicy 参数包括SOURCE注解将被编译器丢弃SOURCE注解将被编译器丢弃CLASS注解在 class 文件中可用但是会被 VM 丢弃。RUNTIMEVM 将在运行期也保留注解因此可以通过反射机制读取注解的信息。Documented将此注解保存在 Javadoc 中Inherited允许子类继承父类的注解Repeatable允许一个注解可以被使用一次或者多次
2. 编写注解处理器
2.1 编写注解处理器
如果没有用于读取注解的工具那么注解不会比注释更有用。使用注解中一个很重要的部分就是创建与使用注解处理器。
下面是一个非常简单的注解处理器我们用它来读取被注解的 PasswordUtils 类并且使用反射机制来寻找 UseCase 标记。
package annotations;import java.lang.reflect.Method;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.IntStream;public class UseCaseTracker {public static voidtrackUseCases(ListInteger useCases, Class? cl) {for (Method m : cl.getDeclaredMethods()) {UseCase uc m.getAnnotation(UseCase.class);if (uc ! null) {System.out.println(Found Use Case uc.id() \n uc.description());useCases.remove(Integer.valueOf(uc.id()));}}useCases.forEach(i -System.out.println(Missing use case i));}public static void main(String[] args) {ListInteger useCases IntStream.range(47, 51).boxed().collect(Collectors.toList());trackUseCases(useCases, PasswordUtils.class);}
}输出
Found Use Case 47Passwords must contain at least one numeric
Found Use Case 49New passwords cant equal previously used ones
Found Use Case 48no description
Missing use case 502.2 注解元素
在 UseCase.java 中定义的 UseCase 的标签包含 int 元素 id 和 String 元素 description。注解元素可用的类型如下所示 所有基本类型int、float、boolean等 String Class enum Annotation 以上类型的数组
2.3 默认值限制
编译器对于元素的默认值有些过于挑剔。首先元素不能有不确定的值。也就是说元素要么有默认值要么就在使用注解时提供元素的值。
这里有另外一个限制任何非基本类型的元素 无论是在源代码声明时还是在注解接口中定义默认值时都不能使用 null 作为其值。这个限制使得处理器很难表现一个元素的存在或者缺失的状态因为在每个注解的声明中所有的元素都存在并且具有相应的值。为了绕开这个约束可以自定义一些特殊的值比如空字符串或者负数用于表达某个元素不存在。
package annotations;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 SimulatingNull {int id() default -1;String description() default ;
}注解不支持继承
3. 使用javac处理注解
通过 javac你可以通过创建编译时compile-time注解处理器在 Java 源文件上使用注解而不是编译之后的 class 文件。
每一个你编写的注解都需要处理器但是 javac 可以非常容易的将多个注解处理器合并在一起。你可以指定多个需要处理的类并且你可以添加监听器用于监听注解处理完成后接到通知。
4. 基于注解的单元测试
单元测试是对类中每个方法提供一个或者多个测试的一种事件其目的是为了有规律的测试一个类中每个部分是否具备正确的行为。在 Java 中最著名的单元测试工具就是 JUnit。JUnit 4 版本已经包含了注解。
5. 本章小结
注解是 Java 引入的一项非常受欢迎的补充它提供了一种结构化并且具有类型检查能力的新途径从而使得你能够为代码中加入元数据而且不会导致代码杂乱并难以阅读。
而 Javadoc 中的 deprecated 被 Deprecated 注解所替代的事实也说明与注释性文字相比注解绝对更适用于描述类相关的信息。
Java 提供了很少的内置注解。这意味着如果你在别处找不到可用的类库那么就只能自己创建新的注解以及相应的处理器。通过将注解处理器链接到 javac你可以一步完成编译新生成的文件简化了构造过程。
API 的提供方和框架将会将注解作为他们工具的一部分。通过 Unit 系统我们可以想象注解会极大的改变我们的 Java 编程体验。 图网侵删