/
DynamicClassCreationExample.java
116 lines (92 loc) · 3.41 KB
/
DynamicClassCreationExample.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
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
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
import io.activej.codegen.ClassBuilder;
import io.activej.codegen.DefiningClassLoader;
import io.activej.codegen.expression.ExpressionToString;
import org.jetbrains.annotations.NotNull;
import static io.activej.codegen.expression.Expressions.*;
/**
* In this example a Class that implements the specified interface is dynamically created.
* Methods are constructed programmatically using our fluent API built on top of ASM.
*/
public class DynamicClassCreationExample {
public static void main(String[] args) throws ReflectiveOperationException {
//[START REGION_2]
Class<Person> personClass = ClassBuilder.create(DefiningClassLoader.create(Thread.currentThread().getContextClassLoader()), Person.class)
// declare fields
.withField("id", int.class)
.withField("name", String.class)
// setter for both fields - a sequence of actions
.withMethod("setIdAndName", sequence(
set(property(self(), "id"), arg(0)),
set(property(self(), "name"), arg(1))))
.withMethod("getId", property(self(), "id"))
.withMethod("getName", property(self(), "name"))
// compareTo, equals, hashCode and toString methods implementations follow the standard convention
.withMethod("int compareTo(Person)", compareToImpl("id", "name"))
.withMethod("equals", equalsImpl("id", "name"))
.withMethod("hashOfPojo", hash(property(arg(0), "id"), property(arg(0), "name")))
.withMethod("hash", hash(property(self(), "id"), property(self(), "name")))
.withMethod("toString", ExpressionToString.create()
.withQuotes("{", "}", ", ")
.with("id: ", property(self(), "id"))
.with("name: ", property(self(), "name")))
.build();
//[END REGION_2]
//[START REGION_3]
// Instantiate two objects of dynamically defined class
Person jack = personClass.getDeclaredConstructor().newInstance();
Person martha = personClass.getDeclaredConstructor().newInstance();
jack.setIdAndName(5, "Jack");
martha.setIdAndName(jack.getId() * 2, "Martha");
System.out.println("First person: " + jack);
System.out.println("Second person: " + martha);
System.out.println("jack.equals(martha) ? : " + jack.equals(martha));
//[END REGION_3]
// Compare dynamically created hashing implementation with the conventional one
ExamplePojo examplePojo = new ExamplePojo(5, "Jack");
System.out.println(examplePojo);
System.out.println("jack.hash(examplePojo) = " + jack.hashOfPojo(examplePojo));
System.out.println("jack.hash() = " + jack.hash());
System.out.println("examplePojo.hashCode() = " + examplePojo.hashCode());
}
//[START REGION_1]
@SuppressWarnings("unused")
public interface Person extends Comparable<Person> {
void setIdAndName(int id, String name);
int getId();
String getName();
int hashOfPojo(ExamplePojo personPojo);
int hash();
@Override
int compareTo(@NotNull Person o);
@Override
String toString();
@Override
boolean equals(Object obj);
}
//[END REGION_1]
@SuppressWarnings("unused")
public static class ExamplePojo {
final int id;
final String name;
ExamplePojo(int id, String name) {
this.id = id;
this.name = name;
}
public int getId() {
return id;
}
public String getName() {
return name;
}
@Override
public int hashCode() {
int result = id;
result = 31 * result + name.hashCode();
return result;
}
@Override
public String toString() {
return "PersonPojo{id=" + id + ", name=" + name + '}';
}
}
}