学习注解和了解lombok的原理
Posted 泡^泡
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了学习注解和了解lombok的原理相关的知识,希望对你有一定的参考价值。
注解的定义
注解通过 @interface 关键字进行定义。
package com;
import java.lang.annotation.*;
public @interface TestSelect {
}
元注解
元注解就是用来修饰注解的。常用的元注解有@Retention和@Target。
- @Retention注解可以理解为设置注解的生命周期。
- @Target表示注解可以修饰哪些地方。(方法、成员变量、包等)
- Documented这个元注解和文档有关。它的作用是能够将注解中的元素包含到 Javadoc 中去。
@Retention
它的取值如下:
- RetentionPolicy.SOURCE:代表注解仅保留在源码中,并由编译器忽略。
- RetentionPolicy.CLASS:代表注解在编译时由编译器保留,但Java虚拟机会忽略。
- RetentionPolicy.RUNTIME:代表着标记的注解会由JVM保留,因此运行时环境可以使用它。
理解这块就得了解从 .java 文件到 class 文件再到 class 被jvm加载的过程了。下面的图描述着从.java文件到编译为class文件的过程。
从这里又引申出:lombok的实现原理就是在这(为什么使用了个@Data这样的注解就能有set/get等方法了,就是在这里加上去的)
@Target
它的取值如下:
- ElementType.ANNOTATION_TYPE 可以给一个注解进行注解。
- ElementType.CONSTRUCTOR 可以给构造方法进行注解
- ElementType.FIELD 可以给属性进行注解。
- ElementType.LOCAL_VARIABLE 可以给局部变量进行注解
- ElementType.METHOD 可以给方法进行注解。
- ElementType.PACKAGE 可以给一个包进行注解。
- ElementType.PARAMETER 可以给一个方法内的参数进行注解。
- ElementType.TYPE 可以给一个类型进行注解,比如类、接口、枚举。
@Inherited
Inherited 是继承的意思,但是它并不是说注解本身可以继承,而是说如果一个超类被 @Inherited 注解过的注解进行注解的话,那么如果它的子类没有被任何注解应用的话,那么这个子类就继承了超类的注解。
@Inherited
@Retention(RetentionPolicy.RUNTIME)
@interface Test {}
@Test
public class A {}
public class B extends A {}
注解 Test 被 @Inherited 修饰,之后类 A 被 Test 注解,类 B 继承 A,类 B 也拥有 Test 这个注解。
@Repeatable
Repeatable 自然是可重复的意思。@Repeatable 是 Java 1.8 才加进来的,所以算是一个新的特性。
什么样的注解会多次应用呢?通常是注解的值可以同时取多个。
举个例子,一个人他既是程序员又是产品经理,同时他还是个画家。
@interface Persons {
Person[] value();
}
@Repeatable(Persons.class)
@interface Person{
String role default "";
}
@Person(role="artist")
@Person(role="coder")
@Person(role="PM")
public class SuperMan{
}
注意上面的代码,@Repeatable 注解了 Person。而 @Repeatable 后面括号中的类相当于一个容器注解。
什么是容器注解呢?就是用来存放其它注解的地方。它本身也是一个注解。
我们再看看代码中的相关容器注解。
@interface Persons {
Person[] value();
}
按照规定,它里面必须要有一个 value 的属性,属性类型是一个被 @Repeatable 注解过的注解数组,注意它是数组。
如果不好理解的话,可以这样理解。Persons 是一张总的标签,上面贴满了 Person 这种同类型但内容不一样的标签。把 Persons 给一个 SuperMan 贴上,相当于同时给他贴了程序员、产品经理、画家的标签。
我们可能对于 @Person(role=”PM”) 括号里面的内容感兴趣,它其实就是给 Person 这个注解的 role 属性赋值为 PM。
注解的属性
注解的属性也叫做成员变量。注解只有成员变量,没有方法。注解的成员变量在注解的定义中以“无形参的方法”形式来声明,其方法名定义了该成员变量的名字,其返回值定义了该成员变量的类型。
package com;
import java.lang.annotation.*;
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
@Documented
public @interface TestSelect {
int id();
String name();
}
默认方法
package com;
import java.lang.annotation.*;
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
@Documented
public @interface TestSelect {
int id() default 0;
String name() default "aaa";
}
直接写属性值
package com;
import java.lang.annotation.*;
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
@Documented
public @interface TestSelect {
String value();
}
package com;
public class Test {
@TestSelect("aaa")
private String name;
}
等同于
package com;
public class Test {
@TestSelect(value = "aaa")
private String name;
}
java里的注解
- @Deprecated:用来标记过时的元素。
- @Override:子类要复写父类中被 @Override 修饰的方法。
- @SuppressWarnings:阻止警告的意思。
- @SafeVarargs:参数安全类型注解。
- @FunctionalInterface:函数式接口注解,这个是 Java 1.8 版本引入的新特性。
注解的提取
提取注解主要使用反射。
1.首先可以通过 Class 对象的 isAnnotationPresent() 方法判断它是否应用了某个注解。
public boolean isAnnotationPresent(Class<? extends Annotation> annotationClass) {}
2.然后通过 getAnnotation() 方法来获取 Annotation 对象。或者是 getAnnotations() 方法。
public <A extends Annotation> A getAnnotation(Class<A> annotationClass) {}
public Annotation[] getAnnotations() {}
前一种方法返回指定类型的注解,后一种方法返回注解到这个元素上的所有注解。
以上是关于学习注解和了解lombok的原理的主要内容,如果未能解决你的问题,请参考以下文章