学而不思则罔,思而不学则殆
【Java】Java注解简单熟悉和了解
引言
最近在学习Retrofit网络请求框架,发现该框架中主要使用注解来封装内部逻辑,使开发的时候调用简洁。因此写一篇文章记录一下注解的相关知识
注解定义
Java 注解是在 JDK5 时引入的新特性,注解(也被称为元数据)为我们在代码中添加信息提供了一种形式化的方法,使我们可以在稍后某个时刻非常方便地使用这些数据。注解类型定义指定了一种新的类型,一种特殊的接口类型。 在关键词 interface 前加 @ 符号也就是用 @interface 来区分注解的定义和普通的接口声明。目前大部分框架(如 Spring Boot 等)都通过使用注解简化了代码并提高的编码效率。
以上注解定义是复制的
注解分类
注解主要分为两类,元注解和普通注解
注解类别 | 说明 | 举例 |
---|---|---|
元注解 | 修饰注解的注解 | @Documented,@Target,@Retention |
普通注解 | 普通注解 | @Override |
元注解
Target
该注解是标识注解使用的范围,取值是ElementType[]类型的数组
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE)
public @interface Target {
/**
* Returns an array of the kinds of elements an annotation type
* can be applied to.
* @return an array of the kinds of elements an annotation type
* can be applied to
*/
ElementType[] value();
}
ElementType详解
ElementType | 原文 | 说明 |
---|---|---|
TYPE | Class, interface (including annotation type), or enum declaration | 修饰类,接口或者枚举 |
FIELD | Field declaration (includes enum constants) | 修饰属性字段 |
METHOD | Method declaration | 修饰方法 |
PARAMETER | Formal parameter declaration | 修饰参数 |
CONSTRUCTOR | Constructor declaration | 修饰构造函数 |
LOCAL_VARIABLE | Local variable declaration | 局部变量声明 |
ANNOTATION_TYPE | Annotation type declaration | 注解类型的说明 |
PACKAGE | Package declaration | 包 |
TYPE_PARAMETER | Type parameter declaration | - |
TYPE_USE | Use of a type | - |
Retention
该注解是描述注解的生命周期
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE)
public @interface Retention {
/**
* Returns the retention policy.
* @return the retention policy
*/
RetentionPolicy value();
}
RetentionPolicy | 说明 | 应用 |
---|---|---|
SOURCE | 源码阶段存在,编译的时候丢弃 | 用作提示 |
CLASS | 存在与字节码中,不会运行到JVM中 | 在编译阶段根据注解生成java代码,比如ButterKnife |
RUNTIME | 运行时存在 | 反射相关的应用,比如Retrofit,效率低 |
普通注解
普通注解就没有啥好说的了,可以随便编写
@Documented
@Target(PARAMETER)
@Retention(RUNTIME)
public @interface Body {}
@Documented
@Target(METHOD)
@Retention(RUNTIME)
public @interface GET {
/**
* A relative or absolute path, or full URL of the endpoint. This value is optional if the first
* parameter of the method is annotated with {@link Url @Url}.
*
* <p>See {@linkplain retrofit2.Retrofit.Builder#baseUrl(HttpUrl) base URL} for details of how
* this is resolved against a base URL to create the full endpoint URL.
*/
String value() default "";
}
@Documented
@Target(METHOD)
@Retention(RUNTIME)
public @interface POST {
/**
* A relative or absolute path, or full URL of the endpoint. This value is optional if the first
* parameter of the method is annotated with {@link Url @Url}.
*
* <p>See {@linkplain retrofit2.Retrofit.Builder#baseUrl(HttpUrl) base URL} for details of how
* this is resolved against a base URL to create the full endpoint URL.
*/
String value() default "";
}
Method之获取注解
在Retrofit方法中有一段代码:
//RequestFactory.java
Builder(Retrofit retrofit, Method method) {
this.retrofit = retrofit;
this.method = method;
this.methodAnnotations = method.getAnnotations();
this.parameterTypes = method.getGenericParameterTypes();
this.parameterAnnotationsArray = method.getParameterAnnotations();
}
根据method获取注解的相关参数,特验证熟悉一下
提供方法:
interface BlogService {
@Multipart
@POST("register")
Call<Blog> registerUser(@PartMap Map<String, RequestBody> params, @Part("password") RequestBody password);
}
Method返回类型
Method method = blogServiceClass.getDeclaredMethod("registerUser", Map.class, RequestBody.class);
Class<?> returnType = method.getReturnType();
Type genericReturnType = method.getGenericReturnType();
System.out.println("returnType:" + returnType);
System.out.println("genericReturnType:" + genericReturnType);
getReturnType返回普通的类型,getGenericReturnType则会返回更加细节,带上了泛型的类型
returnType:interface retrofit2.Call
genericReturnType:retrofit2.Call<com.example.test.AnnotatedTest$Blog>
Method的注解
Annotation[] annotations = method.getAnnotations();
Annotation[] declaredAnnotations = method.getDeclaredAnnotations();
System.out.println(Arrays.toString(annotations));
System.out.println(Arrays.toString(declaredAnnotations));
可以看到,这里返回了registerUser方法的两个注解,Multipart和POST
[@retrofit2.http.Multipart(), @retrofit2.http.POST(value=register)]
[@retrofit2.http.Multipart(), @retrofit2.http.POST(value=register)]
Method的参数
Class<?>[] parameterTypes = method.getParameterTypes();
Type[] genericParameterTypes = method.getGenericParameterTypes();
System.out.println(Arrays.toString(parameterTypes));
System.out.println(Arrays.toString(genericParameterTypes));
同样返回了参数类型列表,差别不同的是,getGenericParameterTypes返回更加细化,携带了泛型类型
[interface java.util.Map, class okhttp3.RequestBody]
[java.util.Map<java.lang.String, okhttp3.RequestBody>, class okhttp3.RequestBody]
Method参数的注解
Annotation[][] parameterAnnotations = method.getParameterAnnotations();
System.out.println(Arrays.deepToString(parameterAnnotations));
这里返回注解的二维数组,因为每个参数可以有多个注解。
[[@retrofit2.http.PartMap(encoding=binary)], [@retrofit2.http.Part(encoding=binary, value=password)]]
注解的相关知识暂时就这些,待后续补充,学习中