- Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathRecordsAndPatterns.java
More file actions
Latest commit
133 lines (120 loc) · 4.5 KB
/
Copy pathRecordsAndPatterns.java
File metadata and controls
133 lines (120 loc) · 4.5 KB
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
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
packagePhase9_ModernJavaAndModules.ModernJava;
/**
* Records (Java 16+) and Record Patterns (Java 21)
* ------------------------------------------------
* A RECORD is a special kind of class introduced in Java 16 for IMMUTABLE
* data carriers. The compiler generates the boilerplate for you:
* <p>
*
* public record Point(int x, int y) {}
* <p>
*
* - Final class, cannot be subclassed.
* - Final fields x and y - immutable after construction.
* - Canonical constructor (int x, int y).
* - Accessor methods: x() and y(). (NOT getX() / getY())
* - equals(), hashCode(), toString() generated based on the components.
* <p>
*
* Why Records?
* ------------
* Before records, a simple data class needed 30+ lines of boilerplate. With
* records:
* <p>
*
* record Point(int x, int y) {} // that's it.
* <p>
*
* Record Patterns (Java 21)
* -------------------------
* Java 21 lets you DECONSTRUCT a record value inside an `instanceof` or a
* switch case, binding the components to local variables:
* <p>
*
* if (obj instanceof Point(int x, int y)) {
* // x and y are usable directly here
* }
* <p>
*
* Record patterns can NEST - deconstruct records inside records:
* <p>
*
* if (shape instanceof Rect(Point(int x1, int y1), Point(int x2, int y2))) {
* ...
* }
* <p>
*
* Customising a Record
* --------------------
* You can add:
* - Static fields and methods.
* - Instance methods (regular or default).
* - A "compact constructor" for validation (see below).
* - Static factory methods.
* You CANNOT add instance fields beyond the components.
*/
publicclassRecordsAndPatterns {
// --- 1) Simple record ---
publicrecordPoint(intx, inty) {}
// --- 2) Record with validation via the compact constructor ---
publicrecordRange(intlow, inthigh) {
publicRange { // compact constructor - no parameter list
if (low > high) {
thrownewIllegalArgumentException("low must be <= high");
}
}
publicintspan() { returnhigh - low; }
}
// --- 3) Nested record for the record-pattern demo ---
publicrecordLine(Pointstart, Pointend) {}
publicstaticvoidmain(String[] args) {
// --- a) Use the auto-generated bits ---
Pointp = newPoint(3, 4);
System.out.println("p.x() = " + p.x());
System.out.println("p.y() = " + p.y());
System.out.println("p = " + p); // Point[x=3, y=4]
Pointp2 = newPoint(3, 4);
System.out.println("p.equals(p2)? " + p.equals(p2)); // true - value equality
// --- b) Compact constructor validates inputs ---
Rangeok = newRange(1, 10);
System.out.println("Range span = " + ok.span());
try {
newRange(5, 2);
} catch (IllegalArgumentExceptione) {
System.out.println("Range rejected: " + e.getMessage());
}
// --- c) Java 21 record pattern with instanceof ---
Objectobj = newPoint(7, 9);
if (objinstanceofPoint(intx, inty)) {
System.out.println("Deconstructed point: x=" + x + ", y=" + y);
}
// --- d) Nested record pattern ---
Objectthing = newLine(newPoint(0, 0), newPoint(3, 4));
if (thinginstanceofLine(Point(intx1, inty1), Point(intx2, inty2))) {
intdx = x2 - x1, dy = y2 - y1;
doubledist = Math.hypot(dx, dy);
System.out.println("Line length = " + dist);
}
// --- e) Record patterns inside a switch expression ---
Objectshape = newLine(newPoint(1, 1), newPoint(4, 5));
Stringdesc = switch (shape) {
casePoint(intx, inty) -> "Point at (" + x + "," + y + ")";
caseLine(Point(intx1, inty1),
Point(intx2, inty2)) -> "Line from (" + x1 + "," + y1 +
") to (" + x2 + "," + y2 + ")";
casenull -> "no shape";
default -> "unknown shape: " + shape;
};
System.out.println(desc);
// OUTPUT
// p.x() = 3
// p.y() = 4
// p = Point[x=3, y=4]
// p.equals(p2)? true
// Range span = 9
// Range rejected: low must be <= high
// Deconstructed point: x=7, y=9
// Line length = 5.0
// Line from (1,1) to (4,5)
}
}