|
| 1 | +# java基础巩固笔记(6)-注解 |
| 2 | + |
| 3 | +标签: java |
| 4 | + |
| 5 | +--- |
| 6 | + |
| 7 | +**Contents** |
| 8 | + |
| 9 | + - [注解的应用结构图](#注解的应用结构图) |
| 10 | + - [元注解](#元注解) |
| 11 | + - [自定义注解](#自定义注解) |
| 12 | + - [示例代码](#示例代码) |
| 13 | + - [参考资料](#参考资料) |
| 14 | + |
| 15 | + |
| 16 | + |
| 17 | +--- |
| 18 | + |
| 19 | + |
| 20 | +注解(Annotation),也叫元数据。一种代码级别的说明。它是JDK1.5及以后版本引入的一个特性,与类、接口、枚举是在同一个层次。它可以声明在包、类、字段、方法、局部变量、方法参数等的前面,用来对这些元素进行说明,注释。 |
| 21 | + |
| 22 | + |
| 23 | +API |
| 24 | + |
| 25 | +> [Package java.lang.annotation](https://docs.oracle.com/javase/8/docs/api/index.html?java/lang/annotation/package-summary.html) |
| 26 | +
|
| 27 | +## 注解的应用结构图 |
| 28 | + |
| 29 | +调用/结构关系:**A<--B<--C** |
| 30 | + |
| 31 | +A,B,C解释如下: |
| 32 | + |
| 33 | +A:注解类 |
| 34 | + |
| 35 | +```java |
| 36 | +@interface A{ |
| 37 | +} |
| 38 | +``` |
| 39 | + |
| 40 | +B:应用了“注解类”的类 |
| 41 | + |
| 42 | +```java |
| 43 | +@A |
| 44 | +Class B{ |
| 45 | +} |
| 46 | +``` |
| 47 | + |
| 48 | +C:对“应用了注解类的类”进行反射操作的类 |
| 49 | + |
| 50 | +```java |
| 51 | +Class C{ |
| 52 | + public void f(){ |
| 53 | + B.class.isAnnotationPresent(A.class); |
| 54 | + A a = B.class.getAnnotion(A.class); |
| 55 | + } |
| 56 | +} |
| 57 | +``` |
| 58 | + |
| 59 | +## 元注解 |
| 60 | + |
| 61 | +元注解的作用就是负责注解其他注解。四个元注解分别是:`@Target,@Retention,@Documented,@Inherited` |
| 62 | + |
| 63 | +- `@Retention` |
| 64 | + |
| 65 | +表示在什么级别保存该注解信息。可选的参数值在枚举类型 `RetentionPolicy`中,包括`RetentionPolicy.SOURCE`,`RetentionPolicy.CLASS`(默认),`RetentionPolicy.RUNTIME`分别对应:java源文件-->class文件-->内存中的字节码 |
| 66 | + |
| 67 | +``` |
| 68 | +RetentionPolicy.SOURCE 注解将被编译器丢弃 |
| 69 | +RetentionPolicy.CLASS 注解在class文件中可用,但会被VM丢弃 |
| 70 | +RetentionPolicy.RUNTIME VM将在运行期也保留注释,因此可以通过反射机制读取注解的信息。 |
| 71 | +``` |
| 72 | + |
| 73 | +- `@Target` |
| 74 | + |
| 75 | +表示该注解用于什么地方,可能的值在枚举类`ElemenetType`中,包括 |
| 76 | + |
| 77 | +``` |
| 78 | +ElemenetType.CONSTRUCTOR 构造器声明 |
| 79 | +ElemenetType.FIELD 域声明(包括 enum 实例) |
| 80 | +ElemenetType.LOCAL_VARIABLE 局部变量声明 |
| 81 | +ElemenetType.METHOD 方法声明 |
| 82 | +ElemenetType.PACKAGE 包声明 |
| 83 | +ElemenetType.PARAMETER 参数声明 |
| 84 | +ElemenetType.TYPE 类,接口(包括注解类型)或enum声明 |
| 85 | +``` |
| 86 | + |
| 87 | +- `@Documented` |
| 88 | + |
| 89 | +将此注解包含在javadoc中 ,它代表着此注解会被javadoc工具提取成文档。在doc文档中的内容会因为此注解的信息内容不同而不同。相当于`@see,@param`等 |
| 90 | + |
| 91 | + |
| 92 | + |
| 93 | +- `@Inherited` |
| 94 | + |
| 95 | +允许子类继承父类中的注解 |
| 96 | + |
| 97 | + |
| 98 | +## 自定义注解 |
| 99 | + |
| 100 | +**使用`@interface`自定义注解时,自动继承了`java.lang.annotation.Annotation`接口,由编译程序自动完成其他细节。在定义注解时,不能继承其他的注解或接口。`@interface`用来声明一个注解,其中的每一个方法实际上是声明了一个配置参数。方法的名称就是参数的名称,返回值类型就是参数的类型(返回值类型只能是基本类型、Class、String、enum)。可以通过default来声明参数的默认值。** |
| 101 | + |
| 102 | + |
| 103 | +定义注解格式: |
| 104 | + |
| 105 | +`public @interface 注解名 {定义体}` |
| 106 | + |
| 107 | +注解参数的可支持数据类型: |
| 108 | + |
| 109 | +1.所有基本数据类型(int,float,boolean,byte,double,char,long,short) |
| 110 | +2.String类型 |
| 111 | +3.Class类型 |
| 112 | +4.enum类型 |
| 113 | +5.Annotation类型 |
| 114 | +6.以上所有类型的数组 |
| 115 | + |
| 116 | + |
| 117 | + |
| 118 | +## 示例代码 |
| 119 | + |
| 120 | +参考文末的[【参考资料】](#参考资料)中[《java 注解的几大作用及使用方法详解(完)》](http://blog.csdn.net/tigerdsh/article/details/8848890) |
| 121 | + |
| 122 | +下面的示例,是上文提到的**A<--B<--C**的扩充版本。自定义了一个注解`@A`,然后在B类中使用了注解`@A`,最后在类C中利用反射读取`@A`中的信息 |
| 123 | + |
| 124 | +- `A.java` |
| 125 | + |
| 126 | +```java |
| 127 | +package com.iot.annotation; |
| 128 | + |
| 129 | +import java.lang.annotation.*; |
| 130 | + |
| 131 | +/** |
| 132 | + * Created by brian on 2016/2/20. |
| 133 | + */ |
| 134 | +@Target({ElementType.TYPE,ElementType.METHOD,ElementType.FIELD,ElementType.CONSTRUCTOR}) |
| 135 | +@Retention(RetentionPolicy.RUNTIME) |
| 136 | +public @interface A { |
| 137 | + String name(); |
| 138 | + int id() default 0; |
| 139 | + Class<Long> gid(); |
| 140 | +} |
| 141 | +``` |
| 142 | + |
| 143 | +- `B.java` |
| 144 | + |
| 145 | +```java |
| 146 | +package com.iot.annotation; |
| 147 | + |
| 148 | +import java.util.HashMap; |
| 149 | +import java.util.Map; |
| 150 | + |
| 151 | +/** |
| 152 | + * Created by brian on 2016/2/20. |
| 153 | + */ |
| 154 | +@A(name="type",gid=Long.class)//类注解 |
| 155 | +public class B { |
| 156 | + @A(name="param",id=1,gid=Long.class) //类成员注解 |
| 157 | + private Integer age; |
| 158 | + |
| 159 | + @A(name="construct",id=2,gid=Long.class) //构造方法注解 |
| 160 | + public B(){} |
| 161 | + |
| 162 | + @A(name="public method",id=3,gid=Long.class) //类方法注解 |
| 163 | + public void a(){ |
| 164 | + |
| 165 | + } |
| 166 | + |
| 167 | + @A(name="protected method",id=4,gid=Long.class) //类方法注解 |
| 168 | + protected void b(){ |
| 169 | + Map<String,String> m = new HashMap<String,String>(0); |
| 170 | + } |
| 171 | + |
| 172 | + |
| 173 | + @A(name="private method",id=5,gid=Long.class) //类方法注解 |
| 174 | + private void c(){ |
| 175 | + Map<String,String> m = new HashMap<String,String>(0); |
| 176 | + } |
| 177 | + |
| 178 | + public void b(Integer a){ |
| 179 | + |
| 180 | + } |
| 181 | +} |
| 182 | + |
| 183 | +``` |
| 184 | + |
| 185 | +- `C.java` |
| 186 | + |
| 187 | +```java |
| 188 | +package com.iot.annotation; |
| 189 | + |
| 190 | +import java.lang.annotation.Annotation; |
| 191 | +import java.lang.reflect.Constructor; |
| 192 | +import java.lang.reflect.Method; |
| 193 | + |
| 194 | +/** |
| 195 | + * Created by brian on 2016/2/20. |
| 196 | + */ |
| 197 | +public class C { |
| 198 | + |
| 199 | + /** |
| 200 | + * 简单打印出B类中所使用到的类注解 |
| 201 | + * 该方法只打印了 Type 类型的注解 |
| 202 | + * @throws ClassNotFoundException |
| 203 | + */ |
| 204 | + public static void parseTypeAnnotation() throws ClassNotFoundException{ |
| 205 | + Class clazz = Class.forName("com.iot.annotation.B"); |
| 206 | + |
| 207 | + Annotation[] annotations = clazz.getAnnotations(); |
| 208 | + for(Annotation annotation :annotations){ |
| 209 | + A a = (A)annotation; |
| 210 | + System.out.println("id = "+a.id()+" ;name = "+a.name()+" ;gid = "+a.gid()); |
| 211 | + } |
| 212 | + |
| 213 | + } |
| 214 | + |
| 215 | + /** |
| 216 | + * 简单打印出B类中所使用到的方法注解 |
| 217 | + * 该方法只打印了 Method 类型的注解 |
| 218 | + */ |
| 219 | + public static void parseMethodAnnotation() { |
| 220 | + Method[] methods = B.class.getDeclaredMethods(); |
| 221 | + for (Method method : methods) { |
| 222 | + /* |
| 223 | + * 判断方法中是否有指定注解类型的注解 |
| 224 | + */ |
| 225 | + boolean hasAnnotation = method.isAnnotationPresent(A.class); |
| 226 | + if (hasAnnotation) { |
| 227 | + /* |
| 228 | + * 根据注解类型返回方法的指定类型注解 |
| 229 | + */ |
| 230 | + A annotation = method.getAnnotation(A.class); |
| 231 | + System.out.println("method = " + method.getName() |
| 232 | + + " ; id = " + annotation.id() + " ; description = " |
| 233 | + + annotation.name() + "; gid= " + annotation.gid()); |
| 234 | + } |
| 235 | + } |
| 236 | + } |
| 237 | + |
| 238 | + /** |
| 239 | + * 简单打印出B类中所使用到的方法注解 |
| 240 | + * 该方法只打印了 Method 类型的注解 |
| 241 | + */ |
| 242 | + public static void parseConstructAnnotation(){ |
| 243 | + Constructor[] constructors = B.class.getConstructors(); |
| 244 | + for (Constructor constructor : constructors) { |
| 245 | + /* |
| 246 | + * 判断构造方法中是否有指定注解类型的注解 |
| 247 | + */ |
| 248 | + boolean hasAnnotation = constructor.isAnnotationPresent(A.class); |
| 249 | + if (hasAnnotation) { |
| 250 | + /* |
| 251 | + * 根据注解类型返回方法的指定类型注解 |
| 252 | + */ |
| 253 | + A annotation =(A) constructor.getAnnotation(A.class); |
| 254 | + System.out.println("constructor = " + constructor.getName() |
| 255 | + + " ; id = " + annotation.id() + " ; description = " |
| 256 | + + annotation.name() + "; gid= "+annotation.gid()); |
| 257 | + } |
| 258 | + } |
| 259 | + } |
| 260 | + |
| 261 | + public static void main(String[] args) throws ClassNotFoundException { |
| 262 | + parseTypeAnnotation(); |
| 263 | + parseMethodAnnotation(); |
| 264 | + parseConstructAnnotation(); |
| 265 | + } |
| 266 | + |
| 267 | +} |
| 268 | + |
| 269 | +``` |
| 270 | + |
| 271 | +## 参考资料 |
| 272 | + |
| 273 | +>* [java 注解的几大作用及使用方法详解(完)](http://blog.csdn.net/tigerdsh/article/details/8848890) |
| 274 | +>* [另类的package-info.java文件探讨](http://strong-life-126-com.iteye.com/blog/806246) |
| 275 | +>* [深入理解Java:注解(Annotation)自定义注解入门](http://www.cnblogs.com/peida/archive/2013/04/24/3036689.html) |
| 276 | +
|
| 277 | + |
| 278 | + |
| 279 | + |
| 280 | +------------ |
| 281 | + |
| 282 | + |
| 283 | +> 作者[@brianway](http://brianway.github.io/)更多文章:[个人网站](http://brianway.github.io/) | [CSDN](http://blog.csdn.net/h3243212/) | [oschina](http://my.oschina.net/brianway) |
| 284 | +
|
0 commit comments