ZB-037-01注解

注解是什么

注解和反射是分不开的
注解和反射是分不开的
注解和反射是分不开的

  • 还记得Class是什么么?
    • Class是Java类的说明书(堆里的某个地方存着)
    • 你(还可以通过反射)或者JVM通过阅读该说明书,创建类的实例
  • 注解就是说明书(class文件)中的⼀⼩段信息/⽂本/标记/标签
    • Annotation @xxx
    • 可以携带参数@xxx(a,b)
    • 可以在运⾏时被阅读

举例

1
2
3
4
5
6
7
你的衣服里,有个说明书写着 涤纶 不可水洗... 一些洗涤信息

狼人杀 的身份 狼人/村民...
王者荣耀的位置 打野/法师/射手/ADC/肉
渣男 ...

这些都是一种标签,它只提供一段“标签” ,怎么处理不由它决定

例子代码 :Spring中的大量注解

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
@Controller
public class AuthController {
private UserService userService;

private AuthenticationManager authentionManager;

@Inject
public AuthController(UserService userService , AuthenticationManager authentionManager) {
this.userService = userService;
this.authentionManager = authentionManager;
}

@GetMapping("/auth")
@ResponseBody //方法的返回值限定在 response body里
public Object auth(){
...
}
}

这就是注解的一切。

为什么加了@xxx 之后就莫名其妙成功了?

  • 注解就是一小段信息,至于怎么处理注解这段信息,不是注解关心的问题

注解的写法

  • 新建⼀个类的时候选择注解 Annotation
  • 元注解(可以放在注解上的注解)
    • @Rentention 编译后可以被保留
    • @Target 可以标记的位置
    • @Documented
    • @Inherited 继承 子类还可以看到这个注解 没卵用
    • @Repeatable 可以重复 平时用不到

写一个我们的注解

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
package com;
// 只提供一个标识,怎么处理 不由它决定
@interface SpringBootApplication {
}

@SpringBootApplication
public class MyApplication {

@SpringBootApplication
private String user;

@SpringBootApplication
public void OrderService(){

}
}
// 可以加在 Class上
// 可以加在 成员变量上
// 可以加在 方法上

注解 @Target@

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
// 只允许放在方法上
@Target(ElementType.METHOD)
@interface SpringBootApplication {
}

// 可以设置 那些地方 可以放置“注解”
@Target({
ElementType.METHOD, // 只允许放在方法上
ElementType.CONSTRUCTOR,// 只允许放在构造器上
ElementType.FIELD,// 只允许放在 字段上
ElementType.TYPE ,// 只允许放在 类型上
ElementType.PARAMETER, // 只允许放在 参数上
ElementType.TYPE_PARAMETER, // 类型参数
ElementType.PACKAGE , // 放在包上
})
@interface SpringBootApplication {
}

@SpringBootApplication
public class MyApplication {

@SpringBootApplication
public MyApplication(String user) {
this.user = user;
}

@SpringBootApplication
private String user;

@SpringBootApplication
public void OrderService(@SpringBootApplication String xx){

}
}

@Retention注解 :编译的时候被保留

1
2
3
4
5
6
7
8
9
@Retention(RetentionPolicy.CLASS) 
@interface SpringBootApplication {
}

// RetentionPolicy.SOURCE 注解会被编译器丢弃
// RetentionPolicy.CLASS 默认行为,会被虚拟机记录下来 记录在 class文件里 但不会被虚拟机运行的时候保留
// RetentionPolicy.RUNTIME 注解会被记录在编译器也会在 虚拟机运行时 保留

// 反射拿不到 SOURCE/CLASS 等级的注解信息

注解的属性

注解的参数可以有哪些?

  • 基本数据类型 + String + Class以及它们的数组
    1
    2


  • 默认值
  • 名为value的属性
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
比如一件外套 
它的说明书(注解)

@洗涤手段([干洗])
class 外套

@洗涤手段([水洗])
class 毛衣

看代码
package com;

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

@Target({
ElementType.METHOD,
ElementType.CONSTRUCTOR,
ElementType.FIELD,
ElementType.TYPE,
ElementType.PARAMETER,
ElementType.TYPE_PARAMETER,
ElementType.PACKAGE
})
@Retention(RetentionPolicy.SOURCE)
@interface 洗涤手段 {

// 属性仅仅支持 基本数据类型 + String + 类 以及它们的数组
String value() default "干洗";
// 成分
String[] 成分() default "纯棉";

// 还可以这样 Class a();
}

@洗涤手段(value ="水洗",成分={"纯棉","涤纶"})
public class 毛衣 {

@洗涤手段
private String name;

@洗涤手段
public void 洗衣服(@洗涤手段 String xx){

}
}

JDK的⾃带注解(了解即可)

  • @Deprecated 提示你这是个被废弃的方法
  • @Override
  • @SuppressWarnings 忽略警告
  • @FunctionalInterface 标记警告 仅仅用来标记 删了也能正常工作

@Override 目的是防止你犯错误

  • 它不是强制的
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
public class Main {
static class Animal{
void xxxx1234567890(){

}
}

static class Cat extends Animal{
@Override
void xxxx1234567890() {
}

// 没有注解 你拼错了 以为自己重写了 实际没有
void xxxx12345678901() {
}
}

public static void main(String[] args) {
}
}

@SuppressWarnings

1
2
3
4
5
6
7
8
// 忽略警告
@SuppressWarnings("unchecked")
public static void main(String[] args) {
List list = new ArrayList<Object>();

list.add(0);
list.get(0);
}

扩展链接