java注解学习

java注解

注解的定义和使用

1
2
3
4
public @interface MyTest {
String[] value();
int id();
}

和接口一样的定义,但前面多了一个@

使用方法

1
2
3
@MyTest
public class MyClass {
}

元注解

字面意思,即最基本的注解。它可以用在其它注解上。
元注解有5种

@Retention 保留期

作用: 其作用是告诉编译器和JVM被注解的注解的存活期

取值 存活期
RetentionPolicy.SOURCE 只在源码阶段,编译时丢弃
RetentionPolicy.CLASS 编译时保留,但不加载入JVM
RetentionPolicy.RUNTIME 编译时保留,加载入JVM,可以获取

@Documented 文档

作用: 它的作用是能够将注解中的元素包含到 Javadoc 中去

@Target 限定注解对象

作用: 限定注解的对象

取值 对象
ElementType.ANNOTATION_TYPE 可以给一个注解进行注解
ElementType.CONSTRUCTOR 可以给构造方法进行注解
ElementType.FIELD 可以给属性进行注解
ElementType.LOCAL_VARIABLE 可以给局部变量进行注解
ElementType.METHOD 可以给方法进行注解
ElementType.PACKAGE 可以给一个包进行注解
ElementType.PARAMETER 可以给一个方法内的参数进行注解
ElementType.TYPE 可以给一个类型进行注解,比如类、接口、枚举

@Inherited 使注解可以随类继承

作用: 使注解可以随类继承

1
2
3
4
5
6
7
8
9
10
11
12
import java.lang.annotation.Inherited;

@Inherited
public @interface MyAnnotation {
}

@MyAnnotation
class test {
}

class test2 extends test {
}

上例中,test2类也有和test类一样的MyAnnotation注解

@Repeatable 重复使用

作用: 对同一类多次打一个注解

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
import java.lang.annotation.Inherited;
import java.lang.annotation.Repeatable;

public @interface MyAnnotation {
role[] value();
}

@Inherited
@Repeatable(MyAnnotation.class)
@interface role {
String value();
}

@role("富豪")
class father {
}

@role("画家")
@role("富二代")
class son extends father {
}

java内置注解

@Deprecated 已抛弃

标记过时的类、属性、方法等

在ide里面,会有删除线表示过时方法

@Override 重写

不多说了

@SuppressWarnings 阻止警告

@SafeVarargs

如果你认为你的方法或者构造方法是类型安全的,那么你也就可以使用@SafeVarargs 来跳过@SuppressWarnings(“unchecked”)检查。

注解的提取

注解通过反射提取

1
2
3
boolean isAnnotationPresent(Class) //是否用了某个注解
<A extends Annotation> A getAnnotation(Class) //获取某个注解类
Annotation[] getAnnotations() //获取所有注解

自己实现的注解默认不被编译器解析,请加上@Retention(RetentionPolicy.RUNTIME)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
import java.lang.annotation.*;
import java.util.Arrays;

@Inherited
@Retention(RetentionPolicy.RUNTIME)
public @interface MyAnnotation {
role[] value();
}

@Inherited
@Repeatable(MyAnnotation.class)
@Retention(RetentionPolicy.RUNTIME)
@interface role {
String value();
}

@role("富豪")
class father {
}

@role("画家")
@role("富二代")
class son extends father {
}

class test {
public static void main(String[] args) {
Annotation[] role = son.class.getAnnotations();
System.out.println(Arrays.toString(role));
}
}


// output
/* >>>
[
@ysoserial.test.role(value=富豪),
@ysoserial.test.MyAnnotation(
value=[
@ysoserial.test.role(value=画家),
@ysoserial.test.role(value=富二代)
]
)
]
*/

作用

给编译器或者APT用,或者说,取决于自己的想法

  • 将需要检查的方法打上@check,来进行检查
  • 利用注解做路由
  • 异步代码标记

实战

下面是一个简单的url路由解析器和定义,文件不多,就5个。带师傅们当个乐就好,主要是去理解其中的含义

RequestMethud.java

1
2
3
4
5
6
package RouteTest.RouteRequest;

public enum RequestMethod {
GET,
POST
}

Request.java

1
2
3
4
5
6
7
8
9
10
11
12
13

package RouteTest.RouteRequest;

import java.lang.annotation.Repeatable;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;

@Repeatable(Requests.class)
@Retention(RetentionPolicy.RUNTIME)
public @interface Request {
String path();
RequestMethod[] method();
}

Requests.java

1
2
3
4
5
6
7
8
9
package RouteTest.RouteRequest;

import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;

@Retention(RetentionPolicy.RUNTIME)
public @interface Requests {
Request[] value();
}

Route.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
package RouteTest.Route;

import RouteTest.RouteRequest.Request;
import static RouteTest.RouteRequest.RequestMethod.*;

public class Route {

@Request(path="/", method = GET)
@Request(path = "/index", method = {GET, POST})
public Object index() {
return "index";
}

@Request(path="/test", method = POST)
public Object test() {
return "test";
}
}

Analysis.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
package RouteTest.RouteAnalysis;

import RouteTest.Route.Route;
import RouteTest.RouteRequest.Request;
import RouteTest.RouteRequest.Requests;

import java.lang.reflect.Method;
import java.util.HashMap;

public class Analysis {
public HashMap<String, Method> RouteAnalysis() {
HashMap<String, Method> urlMap = new HashMap<>();

Route router = new Route();
Method[] r = router.getClass().getDeclaredMethods();

for (Method m : r) {
Request req = getRequest(m);
if (req != null) {
urlMap.put(req.path(), m);
}

Requests reqs = getRequests(m);
if (reqs != null) {
for (Request reqFromReqs : reqs.value()) {
urlMap.put(reqFromReqs.path(), m);
}
}
}

return urlMap;
}

private Request getRequest(Method m) {
return m.getAnnotation(Request.class);
}

private Requests getRequests(Method m) {
return m.getAnnotation(Requests.class);
}
}

class test {
public static void main(String[] args) {
Analysis test = new Analysis();
System.out.println(test.RouteAnalysis().get("/index"));
// output public java.lang.Object RouteTest.Route.Route.index()
}
}

Comments