【狂神说Java】注解和反射

注解

image-20220208113418244

image-20220208114008654

image-20220208130546932

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
package com.zq.Annotation;

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

@Target(value = {ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@interface MyAnnotation {
String name() default "zq";

int age();
}

@Target(value = {ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@interface MyAnnotation2 {
String value();
}

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

@MyAnnotation(age = 18)
public void test() {
}

@MyAnnotation2("jamay")
public void test2() {
}
}

反射

image-20220208134731372image-20220208140641045

image-20220208141021317

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
50
51
52
53
54
55
56
57
58
package com.zq.Reflect;

public class test1 {
public static void main(String[] args) throws ClassNotFoundException {
Class c1 = Class.forName("com.zq.Reflect.user");
System.out.println(c1);
// 一个类只有一个Class对象, 表现为以下hashcode相同

// 对象.getClass()
Class c2 = new user().getClass();
// 类名.class
Class c3 = user.class;

System.out.println(c1.hashCode());
System.out.println(c2.hashCode());
System.out.println(c3.hashCode());

// 基本内置类型.TYPE
Class c4 = Integer.TYPE;
}
}

class user {
private String name;
private int id;

public user(String name, int id) {
this.name = name;
this.id = id;
}

public user() {
}

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

public int getId() {
return id;
}

public void setId(int id) {
this.id = id;
}

@Override
public String toString() {
return "user{" +
"name='" + name + '\'' +
", id=" + id +
'}';
}
}

image-20220208144222455

image-20220208151043760

image-20220208153325517

image-20220208153801345

双亲委派机制

  • 原理:

    • 如果一个类加载器收到了类加载请求,它并不会自己先加载,而是把这个请求委托给父类的加载器去执行
    • 如果父类加载器还存在其父类加载器,则进一步向上委托,依次递归,请求最终将到达顶层的引导类加载器;
    • 如果父类加载器可以完成类加载任务,就成功返回,倘若父类加载器无法完成加载任务,子加载器才会尝试自己去加载,这就是双亲委派机制
    • 父类加载器一层一层往下分配任务,如果子类加载器能加载,则加载此类,如果将加载任务分配至系统类加载器也无法加载此类,则抛出异常
  • 作用:

    • 避免类的重复加载(最开始时没有缓存, 逐步向上, 再向下, 某一层将类加载并缓存. 再次加载时, 已有缓存, 不再向上询问)
    • 保护程序安全,防止核心API被随意篡改

image-20220208155402948

  • 打破双亲委派
    • 自定义类加载器,重写loadClass方法
    • 使用线程上下文类加载器

有了Class对象, 能做什么

image-20220208161345114

创建对象

1
2
Class c1 = Class.forName("com.zq.Reflect.user");
user u = (user)c1.newInstance(); // 调用user的无参构造, 如果没有无参构造会报错
1
2
3
4
Class c1 = Class.forName("com.zq.Reflect.user");
Constructor constructor = c1.getDeclaredConstructor(String.class, int.class);
user zq = (user)constructor.newInstance("zq", 18);// 通过构造器来创建对象
System.out.println(zq);

通过反射调用类中的方法

image-20220208170004387

image-20220208170041825

image-20220208170118010

设置为true可提高效率, 当然远不及直接用正常的方法(new对象,对象调用)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
package com.zq.Reflect;

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

public class Use {
public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException, NoSuchFieldException {
Class c1 = Class.forName("com.zq.Reflect.user");
Constructor constructor = c1.getDeclaredConstructor(String.class, int.class);
user zq = (user) constructor.newInstance("zq", 18);
Method setName = c1.getDeclaredMethod("setName", String.class);
setName.invoke(zq, "jamay");
System.out.println(zq);

Field id = c1.getDeclaredField("id");
id.setAccessible(true);// 关闭安全检测. 才可以操作私有属性
id.set(zq, 20);
System.out.println(zq);

}
}

效率测试

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
50
51
52
package com.zq.Reflect;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

public class EfficiencyTest {
public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {
test1();
test2();
test3();
}

public static void test1() {
user zq = new user("zq", 18);
long startTime = System.currentTimeMillis();
for (int i = 0; i < 1000000000; i++) {
zq.getName();
}
long endTime = System.currentTimeMillis();
System.out.println("正常方式10亿次用时" + (endTime - startTime) + "ms");

}

public static void test2() throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
user zq = new user("zq", 18);
Class c1 = zq.getClass();
Method getName = c1.getDeclaredMethod("getName");
long startTime = System.currentTimeMillis();
for (int i = 0; i < 1000000000; i++) {
getName.invoke(zq, null);
}
long endTime = System.currentTimeMillis();
System.out.println("反射方式10亿次用时" + (endTime - startTime) + "ms");
}

public static void test3() throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
user zq = new user("zq", 18);
Class c1 = zq.getClass();
Method getName = c1.getDeclaredMethod("getName");
getName.setAccessible(true);
long startTime = System.currentTimeMillis();
for (int i = 0; i < 1000000000; i++) {
getName.invoke(zq, null);
}
long endTime = System.currentTimeMillis();
System.out.println("反射方式关闭检测10亿次用时" + (endTime - startTime) + "ms");
}
}

//正常方式10亿次用时9ms
//反射方式10亿次用时2531ms
//反射方式关闭检测10亿次用时1318ms

通过反射操作注解

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
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
package com.zq.Reflect;

import java.lang.annotation.*;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@interface Table {
String value();
}

@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
@interface Column {
String name();

String type();

int length();
}

public class AnnotationAndReflect {
public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException, NoSuchFieldException {
Class c1 = Class.forName("com.zq.Reflect.Student");
Annotation[] annotations = c1.getAnnotations();
for (Annotation annotation : annotations) {
System.out.println(annotation);
}
Table annotation = (Table) c1.getAnnotation(Table.class);
System.out.println(annotation.value());

Field name = c1.getDeclaredField("name");

Column a = name.getAnnotation(Column.class);
System.out.println(a.name());
System.out.println(a.type());
System.out.println(a.length());
}
}

@Table("db_student")
class Student {
@Column(name = "Column_id", type = "int", length = 10)
private int id;
@Column(name = "Column_name", type = "String", length = 10)

private String name;

public Student() {
}

public Student(int id, String name) {
this.id = id;
this.name = name;
}

public int getId() {
return id;
}

public void setId(int id) {
this.id = id;
}

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

@Override
public String toString() {
return "Student{" +
"id=" + id +
", name='" + name + '\'' +
'}';
}
}


/*@com.zq.Reflect.Table(value=db_student)
db_student
Column_name
String
10*/