thinking-in-java(20)注解
【1】注解介绍
1)注解是什么?
注解(元数据)是 java提供的一种对程序元素(如类,方法,变量)打标记的方法;以便运行程序或编译器可以识别这些元素进行特殊处理;最典型的用法是,框架代码启动时扫描某注解修饰的所有类并将其加载到内存,以构建系统底层框架,更直白点,类,方法,变量被注解修饰后,更容易被识别以便加载;
补充: 显然,开发或学习底层框架的同学肯定必不可少要学习注解;所以注解是相当重要的;
【2】java内置的三种注解
1)@Override: 表示被标记的方法将覆盖超类中的方法;
2)@Deprecated:表示被标记的元素(类或方法)被废弃了 ; 如果代码使用该元素,则编译器会发出警告;
3)@SuppressWarnings:关闭不当的编译器警告信息;
【3】4种标准元注解
1)元注解:元注解的作用是负责修饰其他注解(参与其他注解的定义或声明)。 java5.0 定义了4个标准的元注解类型; (干货——你也可以认为被注解修饰,就是被注解打标记)
1.1)@Target元注解,用于指定被修饰注解可以应用到哪些元素上;
如 注解可以被应用到 packages,type(类,接口,枚举,Annotation类),类型成员(方法,构造方法,成员变量,枚举值),方法参数和本地变量等;
注解定义例子1:
@Target(ElementType.METHOD) // 表示用于修饰(标记)方法
@Retention(RetentionPolicy.RUNTIME) // 表示运行时可用
public @interface Test {} ///:~
注解应用例子1:
public class Testable {public void execute() {System.out.println("Executing..");}@Test // Test 注解用于修饰方法void testExecute() {execute();}
}
1.2)@Retention元注解,用于指定被修饰注解的生命周期;
- SOURCE:源文件有效;被编译器丢弃;
- CLASS:class文件有效;被JVM丢弃;
- RUNTIME :运行时有效(常用);VM将在运行期也保留注解,通过反射机制读取注解;
1.3)@Document 用于指定被修饰的注解可以被 javadoc 工具文档化;
1.4)@Inherited 用于指定被修饰的注解是可以被继承的
2)上面例子中修饰的注解 Test,是没有任何成员方法的。下面我们来看有成员方法的注解UseCase;·
// 下面定义了一个注解UseCase:该注解作用于方法,该注解在运行时发挥作用
// 该注解UseCase应用于什么地方
@Target(ElementType.METHOD)
// 该注解UseCase的应用级别,源代码-SOURCE, 类文件中-CLASS, 运行时-RUNTIME
@Retention(RetentionPolicy.RUNTIME)
public @interface UseCase {public int id();public String description() default "no description"; // no description 是默认值
}
/*
D:\workbench_idea\study4vw\thinkinjava\src>javap chapter20.UseCase
Compiled from "UseCase.java"
public interface chapter20.UseCase extends java.lang.annotation.Annotation {public abstract int id();public abstract java.lang.String description();
}
*/
反编译(javap)后的源码:可以看到,注解就是一个接口,该接口的父类是 Annotation 注解接口类型,当然了,接口中的方法都是抽象方法。
2.1)使用 UseCase注解;
// 荔枝-有3个方法被注解UseCase修饰为用例
public class PasswordUtils {// 将 UseCase 注解作用于方法@UseCase(id = 47, description = "validatePassword method")public boolean validatePassword(String password) {return (password.matches("\\w*\\d\\w*"));}@UseCase(id = 48) // description 默认为 no descriptionpublic String encryptPassword(String password) {return new StringBuilder(password).reverse().toString();}@UseCase(id = 49, description = "checkForNewPassword method")public boolean checkForNewPassword(List<String> prevPasswords, String password) {return !prevPasswords.contains(password);}
}
/* 反编译简要结果如下:
D:\workbench_idea\study4vw\thinkinjava\src>javap chapter20.PasswordUtils
Compiled from "PasswordUtils.java"
public class chapter20.PasswordUtils {public chapter20.PasswordUtils();public boolean validatePassword(java.lang.String);public java.lang.String encryptPassword(java.lang.String);public boolean checkForNewPassword(java.util.List<java.lang.String>, java.lang.String);
}
*/
解析注解
/*** 注解解析测试用例*/
public class AnnotationDiyTest {public final static <T> void f1(Class<T> c1) {for (Method method : c1.getMethods()) { // 获取类定义方法UseCase useCase = method.getAnnotation(UseCase.class); // 获取方法上某个注解if (useCase != null) {System.out.println(useCase.id() + "-" + useCase.description()); // 解析注解}}}public static void main(String[] args) {f1(PasswordUtils.class);}
}
/*
47-validatePassword method
48-no description
49-checkForNewPassword method
*/
【4】自定义注解
UseCase注解有两个方法,方法返回类型有 int,String;此外还有其他返回类型,包括
所有基本类型;
String;
Class
enum;
Annotation;// 注解的成员方法的返回值类型还可以是注解类型
以及以上类型的数组;
下面定义一个嵌套注解(即注解的方法返回类型是注解类型)
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface SQLString {int value() default 0;String name() default "";Constraints constraints() default @Constraints();// 嵌套注解
} // /:~
// 定义注解(并定义嵌套注解)
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface SQLInteger {int value() default 0;String name() default "";// 嵌套注解,因为 Constraints 也是注解类型Constraints constraints() default @Constraints;
} // /:~
// 荔枝-定义注解(并定义嵌套注解)
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface SQLDouble {double value() default 0f;// 嵌套注解,因为 Constraints 也是注解类型Constraints constraints() default @Constraints;
}
// 荔枝-定义注解用于生成一个数据库表
@Target(ElementType.TYPE) // 注解作用于哪里(注解的作用对象)
// Applies to classes only
@Retention(RetentionPolicy.RUNTIME) // 注解的作用时间(这里是运行时)
public @interface DBTable {// DBTable 有一个name元素// 这个注解通过使用 value元素 为处理器创建数据库表提供的表名public String value() default "";
} // /:~
// 荔枝-为修饰 javabean域 准备的注解
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Constraints {boolean primaryKey() default false; // 主键boolean allowNull() default true; // 允许为空boolean unique() default false; // 唯一键
} // /:~
使用注解创建数据库表对应的javabean
// DBTable 注解作用于类
@DBTable("MEMBER")
public class Member {@SQLString(30) String firstName;@SQLString(value=50, name = "lastName") String lastName;@SQLInteger(name = "age", constraints = @Constraints(primaryKey=true, allowNull=false, unique=true)) Integer age;@SQLString(value = 30 , name = "handle", constraints = @Constraints(primaryKey = true))String handle;static int memberCount;public String getHandle() {return handle;}public String getFirstName() {return firstName;}public String getLastName() {return lastName;}public String toString() {return handle;}public Integer getAge() {return age;}
} // /:~
使用注解的快捷方式:如果注解中定义了名为value元素(value方法),且在使用注解时,该元素是唯一一个需要复制的元素,那么只需要给出value元素的值即可,无需写键值对形式
@DBTable("MEMBER")-快捷方式 , @DBTable(value="MEMBER")-普通方式
【5】使用apt处理注解
1)问题, 上述代码中,都需要为注解编写处理器以解析注解; 很麻烦;
使用 apt类库方法可以生成注解处理器,apt 是使用源代码生成注解的,无法通过class文件获取类的属性;但 mirror api 可以允许程序员在源代码中查看类属性,如方法,属性;
2)注解
// 抽取注解
@Target(ElementType.TYPE) //
@Retention(RetentionPolicy.SOURCE) // 在源文件起作用
public @interface ExtractInterface {public String value();
} // /:~
【6】小结
java se5仅提供了很少的注解,大多数情况下,需要自定义注解及注解处理器(特别是开发底层框架的时候,需要自定义注解);
javassist 能够用来操作字节码;mirror api 能够用来找出java源代码中的元素 (apt-mirror-api maven repo);
thinking-in-java(20)注解相关推荐
- java spring框架 注解_史上最全的java spring注解
史上最全的java spring注解,没有之一 注解是个好东西,但好东西我们也是看见过,整理过,理解过,用过才知道好.不求我们每个都记住,但求保有印象,在需要的时候能提取出来再查找相关资料,平时工作就 ...
- JAVA配置注解方式搭建简单的SpringMVC前后台交互系统
前面两篇文章介绍了 基于XML方式搭建SpringMVC前后台交互系统的方法,博文链接如下: http://www.cnblogs.com/hunterCecil/p/8252060.html htt ...
- java自定义注解为空值_java自定义注解
1. Java注解(Annotation) Java注解是附加在代码中的一些元信息,用于一些工具在编译. 运行时进行解析和使用,起到说明.配置的功能. 注解相关类都包含在java.lang.annot ...
- 深入理解Java:注解(Annotation)基本概念、自定义注解、注解解析器
深入理解Java:注解(Annotation)基本概念 什么是注解(Annotation): Annotation(注解)就是Java提供了一种元程序中的元素关联任何信息和着任何元数据(metadat ...
- @async注解_史上最全的java spring注解
史上最全的java spring注解,没有之一 注解是个好东西,但好东西我们也是看见过,整理过,理解过,用过才知道好.不求我们每个都记住,但求保有印象,在需要的时候能提取出来再查找相关资料,平时工作就 ...
- Java基于注解和反射导入导出Excel
代码地址如下: http://www.demodashi.com/demo/11995.html 1. 构建项目 使用Spring Boot快速构建一个Web工程,并导入与操作Excel相关的POI包 ...
- java path 注解_Java内置系统注解和元注解
第一节:注解(Annotation)的作用 Annotation(注解)是JDK5.0及以后版本引入的.它的作用是修饰程序元素.什么是程序元素呢?例如:包.类.构造方法.方法.成员变量等. 注解,就是 ...
- java自定义注解枚举_java_自定义注解
1 注解的定义和用途 1.1 官方描述 An annotation is a form of metadata, that can be added to Java source code. Clas ...
- 全网最全的JAVA所有版本特性【JAVA 1.0 - JAVA 20】
闲来想了解下各版本之间的特性,搜索没有最新的特性说明,故想写一份.废话不多说. PS:绝对全网最全最齐,若不是,请私聊我补充,哈哈哈哈! JDK Version 1.0 1996-01-23 Oak( ...
- 夯实 Java 基础 - 注解
夯实 Java 基础 - 注解 不知道大家有没有一种感觉,当你想要了解某个知识点的时候,就会发现好多技术类 APP 或者公众号在推一些关于这个知识点的文章.也许这就是大数据的作用,这也说明总有人比你抢 ...
最新文章
- note-在VisualStudio中使用正则表达式
- 新手必须掌握的学车技巧-上坡起步
- 最全的mysql 5.7.13_最全的mysql 5.7.13 安装配置方法图文教程(linux) 强烈推荐!
- Java使用Springboot集成Es官方推荐(RestHighLevelClient)
- 10款你应该了解的开源安全工具
- eBPF and IO Visor: The what, how, and what next!
- 在线图片转base64工具
- 中英文对照 —— 色彩的描述
- 在linux缓存里写数据,缓存策略
- html字体外颜色轮廓,文字轮廓效果
- 信息安全技术国家相关标准一览表
- WIN10教育版激活方法
- 现在程序员的工资是不是被高估了?
- 创业团队:太极图形团队
- 使用Spring Environment遇到的问题, 如读取到配置不是自己实际想要的
- windows NTFS文件系统手动数据恢复
- win10 自带截图工具 SnippingTool
- PotPlayer 绿色版下载安装、直播 CCTV
- 下载maven私服所有jar包
- Android 后台保活,这里有你需要的所有姿势。2019,flutterlistview滚动卡顿
热门文章
- P3327 [SDOI2015]约数个数和
- CF1270H Number of Components(线段树)
- Caddi Programming Contest 2021(AtCoder Beginner Contest 193) 题解
- 粉刷木板(ybtoj-单调队列)
- P3244-[HNOI2015]落忆枫音【dp】
- jzoj4637-大鱼海棠【博弈论】
- P4562-[JXOI2018]游戏【数论,组合数学】
- jzoj5231-序列问题【分治】
- 3、数据库中的字符集和校对集
- 对Java的URL类支持的协议进行扩展的方法