oh-my-customcode 0.30.8 → 0.31.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +4 -3
- package/package.json +1 -1
- package/templates/CLAUDE.md.en +1 -0
- package/templates/CLAUDE.md.ko +1 -0
- package/templates/guides/flutter/performance.md +1 -1
- package/templates/guides/java21/index.yaml +29 -0
- package/templates/guides/java21/java-style-guide.md +248 -0
- package/templates/guides/java21/modern-java21.md +303 -0
- package/templates/manifest.json +2 -2
- package/templates/.claude/skills/go-best-practices/CLAUDE.md +0 -9
package/README.md
CHANGED
|
@@ -21,7 +21,7 @@ Like oh-my-zsh transformed shell customization, oh-my-customcode makes personali
|
|
|
21
21
|
|
|
22
22
|
| Feature | Description |
|
|
23
23
|
|---------|-------------|
|
|
24
|
-
| **Batteries Included** | 44 agents, 68 skills,
|
|
24
|
+
| **Batteries Included** | 44 agents, 68 skills, 25 guides, 18 rules, 2 hooks, 4 contexts, ontology graph - ready to use out of the box |
|
|
25
25
|
| **Sub-Agent Model** | Supports hierarchical agent orchestration with specialized roles |
|
|
26
26
|
| **Dead Simple Customization** | Create a folder + markdown file = new agent or skill |
|
|
27
27
|
| **Mix and Match** | Use built-in components, create your own, or combine both |
|
|
@@ -197,7 +197,7 @@ All commands are invoked inside the Claude Code conversation.
|
|
|
197
197
|
| **Deploy** | 2 | vercel-deploy, codex-exec |
|
|
198
198
|
| **External** | 1 | skills-sh-search |
|
|
199
199
|
|
|
200
|
-
### Guides (
|
|
200
|
+
### Guides (25)
|
|
201
201
|
|
|
202
202
|
Comprehensive reference documentation covering:
|
|
203
203
|
- Agent creation and management
|
|
@@ -292,7 +292,8 @@ your-project/
|
|
|
292
292
|
│ ├── rules/ # Behavior rules (18 total)
|
|
293
293
|
│ ├── hooks/ # Event hooks (2 total)
|
|
294
294
|
│ └── contexts/ # Context files (4 total)
|
|
295
|
-
└──
|
|
295
|
+
└── templates/
|
|
296
|
+
└── guides/ # Reference docs (25 total)
|
|
296
297
|
```
|
|
297
298
|
|
|
298
299
|
**Note**: In the official Claude Code format, there is no command registry — slash commands and natural language agent references are used.
|
package/package.json
CHANGED
package/templates/CLAUDE.md.en
CHANGED
|
@@ -168,6 +168,7 @@ Violation = immediate correction. No exception for "small changes".
|
|
|
168
168
|
| `/optimize-analyze` | Analyze bundle and performance |
|
|
169
169
|
| `/optimize-bundle` | Optimize bundle size |
|
|
170
170
|
| `/optimize-report` | Generate optimization report |
|
|
171
|
+
| `/research` | 10-team parallel deep analysis and cross-verification |
|
|
171
172
|
| `/sauron-watch` | Full R017 verification |
|
|
172
173
|
| `/structured-dev-cycle` | 6-stage structured development cycle (Plan → Verify → Implement → Verify → Compound → Done) |
|
|
173
174
|
| `/lists` | Show all available commands |
|
package/templates/CLAUDE.md.ko
CHANGED
|
@@ -168,6 +168,7 @@ oh-my-customcode로 구동됩니다.
|
|
|
168
168
|
| `/optimize-analyze` | 번들 및 성능 분석 |
|
|
169
169
|
| `/optimize-bundle` | 번들 크기 최적화 |
|
|
170
170
|
| `/optimize-report` | 최적화 리포트 생성 |
|
|
171
|
+
| `/research` | 10-team 병렬 딥 분석 및 교차 검증 |
|
|
171
172
|
| `/sauron-watch` | 전체 R017 검증 |
|
|
172
173
|
| `/structured-dev-cycle` | 6단계 구조적 개발 사이클 (Plan → Verify → Implement → Verify → Compound → Done) |
|
|
173
174
|
| `/lists` | 모든 사용 가능한 커맨드 표시 |
|
|
@@ -80,7 +80,7 @@ Detect with: DevTools → Rendering → "Highlight repaints"
|
|
|
80
80
|
|
|
81
81
|
| Avoid | Use Instead | Reason |
|
|
82
82
|
|-------|-------------|--------|
|
|
83
|
-
| `Opacity` widget | `color.
|
|
83
|
+
| `Opacity` widget | `color.withValues(alpha: 0.5)` | Opacity widget triggers saveLayer |
|
|
84
84
|
| `ClipRRect` in animations | Pre-clip static content | saveLayer per frame |
|
|
85
85
|
| `Container` for sizing | `SizedBox` | Lighter, no decoration |
|
|
86
86
|
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
# Java 21 Guide
|
|
2
|
+
|
|
3
|
+
metadata:
|
|
4
|
+
name: java21
|
|
5
|
+
description: Java 21 language reference and modern feature documentation
|
|
6
|
+
|
|
7
|
+
source:
|
|
8
|
+
type: external
|
|
9
|
+
origin: docs.oracle.com
|
|
10
|
+
urls:
|
|
11
|
+
- https://docs.oracle.com/en/java/javase/21/
|
|
12
|
+
- https://openjdk.org/projects/loom/
|
|
13
|
+
- https://openjdk.org/jeps/440
|
|
14
|
+
- https://openjdk.org/jeps/441
|
|
15
|
+
- https://openjdk.org/jeps/444
|
|
16
|
+
- https://google.github.io/styleguide/javaguide.html
|
|
17
|
+
last_fetched: "2026-03-11"
|
|
18
|
+
|
|
19
|
+
documents:
|
|
20
|
+
- name: modern-java21
|
|
21
|
+
path: ./modern-java21.md
|
|
22
|
+
description: Java 21 modern features (Virtual Threads, Pattern Matching, Records, Sealed Classes)
|
|
23
|
+
|
|
24
|
+
- name: java-style-guide
|
|
25
|
+
path: ./java-style-guide.md
|
|
26
|
+
description: Google Java Style Guide conventions
|
|
27
|
+
|
|
28
|
+
used_by:
|
|
29
|
+
- lang-java21-expert
|
|
@@ -0,0 +1,248 @@
|
|
|
1
|
+
# Java Style Guide
|
|
2
|
+
|
|
3
|
+
> Source: https://google.github.io/styleguide/javaguide.html
|
|
4
|
+
|
|
5
|
+
## File Structure
|
|
6
|
+
|
|
7
|
+
```
|
|
8
|
+
Source file:
|
|
9
|
+
1. License/copyright (if any)
|
|
10
|
+
2. Package statement
|
|
11
|
+
3. Import statements
|
|
12
|
+
4. Exactly one top-level class
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
### Import Ordering
|
|
16
|
+
|
|
17
|
+
```java
|
|
18
|
+
// 1. Static imports (all together)
|
|
19
|
+
import static org.junit.Assert.assertEquals;
|
|
20
|
+
|
|
21
|
+
// 2. Non-static imports (all together, no subgroups)
|
|
22
|
+
import com.example.Foo;
|
|
23
|
+
import java.util.List;
|
|
24
|
+
import org.springframework.boot.SpringApplication;
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
No wildcard imports except `static` test imports.
|
|
28
|
+
|
|
29
|
+
---
|
|
30
|
+
|
|
31
|
+
## Naming Conventions
|
|
32
|
+
|
|
33
|
+
| Element | Style | Example |
|
|
34
|
+
|---------|-------|---------|
|
|
35
|
+
| Packages | `lowercase` | `com.example.network` |
|
|
36
|
+
| Classes | `UpperCamelCase` | `OrderProcessor` |
|
|
37
|
+
| Records | `UpperCamelCase` | `UserRecord` |
|
|
38
|
+
| Methods | `lowerCamelCase` | `processOrder()` |
|
|
39
|
+
| Local vars | `lowerCamelCase` | `itemCount` |
|
|
40
|
+
| Constants | `UPPER_SNAKE_CASE` | `MAX_RETRIES` |
|
|
41
|
+
| Type params | Single letter or `UpperCamelCase + T` | `T`, `E`, `RequestT` |
|
|
42
|
+
|
|
43
|
+
### Acronyms
|
|
44
|
+
|
|
45
|
+
Treat acronyms as words: `XmlParser`, not `XMLParser`. Exception: well-known 2-letter ones like `IO`.
|
|
46
|
+
|
|
47
|
+
---
|
|
48
|
+
|
|
49
|
+
## Formatting
|
|
50
|
+
|
|
51
|
+
### Indentation
|
|
52
|
+
|
|
53
|
+
- 2 spaces (not tabs) for block indentation
|
|
54
|
+
- 4 spaces for line continuation
|
|
55
|
+
|
|
56
|
+
```java
|
|
57
|
+
// Block indentation: 2 spaces
|
|
58
|
+
if (condition) {
|
|
59
|
+
doSomething();
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
// Line continuation: 4 spaces
|
|
63
|
+
String result = longMethodName(
|
|
64
|
+
argument1,
|
|
65
|
+
argument2);
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
### Braces
|
|
69
|
+
|
|
70
|
+
Always use braces, even for single-statement bodies:
|
|
71
|
+
|
|
72
|
+
```java
|
|
73
|
+
// Correct
|
|
74
|
+
if (condition) {
|
|
75
|
+
doSomething();
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
// Wrong (no braces)
|
|
79
|
+
if (condition)
|
|
80
|
+
doSomething();
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
### Column Limit
|
|
84
|
+
|
|
85
|
+
100 characters per line. Wrap when exceeding.
|
|
86
|
+
|
|
87
|
+
### Blank Lines
|
|
88
|
+
|
|
89
|
+
```java
|
|
90
|
+
class MyClass {
|
|
91
|
+
private int field; // field
|
|
92
|
+
// one blank line
|
|
93
|
+
public MyClass() { } // constructor
|
|
94
|
+
// one blank line
|
|
95
|
+
public void method() { } // method
|
|
96
|
+
}
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
---
|
|
100
|
+
|
|
101
|
+
## Class Structure
|
|
102
|
+
|
|
103
|
+
```java
|
|
104
|
+
public class MyClass {
|
|
105
|
+
// 1. Static fields
|
|
106
|
+
private static final Logger log = LoggerFactory.getLogger(MyClass.class);
|
|
107
|
+
|
|
108
|
+
// 2. Instance fields
|
|
109
|
+
private final String name;
|
|
110
|
+
|
|
111
|
+
// 3. Constructors
|
|
112
|
+
public MyClass(String name) {
|
|
113
|
+
this.name = name;
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
// 4. Static factory methods (if applicable)
|
|
117
|
+
public static MyClass of(String name) {
|
|
118
|
+
return new MyClass(name);
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
// 5. Instance methods (public → package → protected → private)
|
|
122
|
+
public String getName() { return name; }
|
|
123
|
+
|
|
124
|
+
private void helper() { }
|
|
125
|
+
|
|
126
|
+
// 6. Inner classes/interfaces (last)
|
|
127
|
+
}
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
---
|
|
131
|
+
|
|
132
|
+
## Programming Practices
|
|
133
|
+
|
|
134
|
+
### Annotations
|
|
135
|
+
|
|
136
|
+
```java
|
|
137
|
+
// One annotation per line for class/method
|
|
138
|
+
@Override
|
|
139
|
+
@Nullable
|
|
140
|
+
public String format(String input) { }
|
|
141
|
+
|
|
142
|
+
// Multiple short annotations on one line for field is OK
|
|
143
|
+
@Nullable @Deprecated String field;
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
### Numeric Literals
|
|
147
|
+
|
|
148
|
+
```java
|
|
149
|
+
long big = 1_000_000L;
|
|
150
|
+
double pi = 3.14_159;
|
|
151
|
+
int hex = 0xFF_EC_D1_8C;
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
### Switch Expressions (prefer over statements)
|
|
155
|
+
|
|
156
|
+
```java
|
|
157
|
+
// Prefer switch expression
|
|
158
|
+
int days = switch (month) {
|
|
159
|
+
case JANUARY, MARCH, MAY, JULY, AUGUST, OCTOBER, DECEMBER -> 31;
|
|
160
|
+
case APRIL, JUNE, SEPTEMBER, NOVEMBER -> 30;
|
|
161
|
+
case FEBRUARY -> 28;
|
|
162
|
+
};
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
### Avoid Long Methods
|
|
166
|
+
|
|
167
|
+
Keep methods short and focused. Extract helpers for blocks exceeding ~20 lines.
|
|
168
|
+
|
|
169
|
+
---
|
|
170
|
+
|
|
171
|
+
## Javadoc
|
|
172
|
+
|
|
173
|
+
### Required for
|
|
174
|
+
|
|
175
|
+
- Every `public` class, interface, enum, record
|
|
176
|
+
- Every `public` or `protected` method (unless trivially obvious)
|
|
177
|
+
|
|
178
|
+
### Format
|
|
179
|
+
|
|
180
|
+
```java
|
|
181
|
+
/**
|
|
182
|
+
* Returns the user associated with the given ID.
|
|
183
|
+
*
|
|
184
|
+
* <p>This method performs a database lookup. It is safe to call
|
|
185
|
+
* from multiple threads.
|
|
186
|
+
*
|
|
187
|
+
* @param id the user identifier (must be positive)
|
|
188
|
+
* @return the user, or empty if not found
|
|
189
|
+
* @throws IllegalArgumentException if {@code id <= 0}
|
|
190
|
+
*/
|
|
191
|
+
public Optional<User> findById(long id) { }
|
|
192
|
+
```
|
|
193
|
+
|
|
194
|
+
### Inline Tags
|
|
195
|
+
|
|
196
|
+
```java
|
|
197
|
+
/**
|
|
198
|
+
* See {@link UserRepository} for persistence details.
|
|
199
|
+
* Use {@code null} to reset the state.
|
|
200
|
+
*/
|
|
201
|
+
```
|
|
202
|
+
|
|
203
|
+
### Prohibited: Non-Javadoc Comments for API
|
|
204
|
+
|
|
205
|
+
```java
|
|
206
|
+
// Wrong: plain comment for public method
|
|
207
|
+
// Returns the user by id
|
|
208
|
+
public Optional<User> findById(long id) { }
|
|
209
|
+
|
|
210
|
+
// Correct: Javadoc
|
|
211
|
+
/** Returns the user by id, or empty if not found. */
|
|
212
|
+
public Optional<User> findById(long id) { }
|
|
213
|
+
```
|
|
214
|
+
|
|
215
|
+
---
|
|
216
|
+
|
|
217
|
+
## Common Antipatterns to Avoid
|
|
218
|
+
|
|
219
|
+
```java
|
|
220
|
+
// ❌ Raw types
|
|
221
|
+
List list = new ArrayList();
|
|
222
|
+
// ✓
|
|
223
|
+
List<String> list = new ArrayList<>();
|
|
224
|
+
|
|
225
|
+
// ❌ String concatenation in loop
|
|
226
|
+
String s = "";
|
|
227
|
+
for (String item : items) s += item;
|
|
228
|
+
// ✓
|
|
229
|
+
StringBuilder sb = new StringBuilder();
|
|
230
|
+
for (String item : items) sb.append(item);
|
|
231
|
+
String s = sb.toString();
|
|
232
|
+
|
|
233
|
+
// ❌ Return null for collections
|
|
234
|
+
public List<String> getItems() { return null; }
|
|
235
|
+
// ✓
|
|
236
|
+
public List<String> getItems() { return Collections.emptyList(); }
|
|
237
|
+
|
|
238
|
+
// ❌ Catch Exception broadly
|
|
239
|
+
try { process(); } catch (Exception e) { }
|
|
240
|
+
// ✓
|
|
241
|
+
try { process(); } catch (IOException e) { log.error("IO error", e); }
|
|
242
|
+
|
|
243
|
+
// ❌ Mutable public field
|
|
244
|
+
public String name;
|
|
245
|
+
// ✓
|
|
246
|
+
private String name;
|
|
247
|
+
public String getName() { return name; }
|
|
248
|
+
```
|
|
@@ -0,0 +1,303 @@
|
|
|
1
|
+
# Modern Java 21 Features
|
|
2
|
+
|
|
3
|
+
> Sources: https://openjdk.org/jeps/ (JEP 431, 440, 441, 444)
|
|
4
|
+
|
|
5
|
+
## Virtual Threads (JEP 444)
|
|
6
|
+
|
|
7
|
+
Virtual Threads are lightweight threads managed by the JVM, enabling millions of concurrent tasks without thread pool tuning.
|
|
8
|
+
|
|
9
|
+
### Key Properties
|
|
10
|
+
|
|
11
|
+
| Property | Platform Thread | Virtual Thread |
|
|
12
|
+
|----------|----------------|----------------|
|
|
13
|
+
| Creation cost | High (OS thread) | Low (JVM-managed) |
|
|
14
|
+
| Memory footprint | ~1MB per thread | ~few KB |
|
|
15
|
+
| Blocking behavior | Blocks OS thread | Unmounts carrier thread |
|
|
16
|
+
| Pooling | Needed | Not recommended |
|
|
17
|
+
|
|
18
|
+
### Usage
|
|
19
|
+
|
|
20
|
+
```java
|
|
21
|
+
// Virtual Thread executor (preferred for I/O-bound tasks)
|
|
22
|
+
try (var executor = Executors.newVirtualThreadPerTaskExecutor()) {
|
|
23
|
+
List<Future<String>> futures = IntStream.range(0, 10_000)
|
|
24
|
+
.mapToObj(i -> executor.submit(() -> fetchData(i)))
|
|
25
|
+
.toList();
|
|
26
|
+
// all 10,000 tasks run concurrently
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
// Direct creation
|
|
30
|
+
Thread.ofVirtual().name("vt-worker").start(() -> processRequest());
|
|
31
|
+
|
|
32
|
+
// Factory for thread pools
|
|
33
|
+
ThreadFactory factory = Thread.ofVirtual().name("worker-", 0).factory();
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
### Structured Concurrency (JEP 453, Preview)
|
|
37
|
+
|
|
38
|
+
```java
|
|
39
|
+
try (var scope = new StructuredTaskScope.ShutdownOnFailure()) {
|
|
40
|
+
Future<String> user = scope.fork(() -> fetchUser(id));
|
|
41
|
+
Future<String> orders = scope.fork(() -> fetchOrders(id));
|
|
42
|
+
|
|
43
|
+
scope.join().throwIfFailed();
|
|
44
|
+
|
|
45
|
+
return new UserProfile(user.get(), orders.get());
|
|
46
|
+
}
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
### Pinning Avoidance
|
|
50
|
+
|
|
51
|
+
Virtual Threads are **pinned** (cannot unmount) inside `synchronized` blocks. Prefer `ReentrantLock`:
|
|
52
|
+
|
|
53
|
+
```java
|
|
54
|
+
// Avoid (causes pinning)
|
|
55
|
+
synchronized (lock) {
|
|
56
|
+
callBlockingIO();
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
// Prefer
|
|
60
|
+
private final ReentrantLock lock = new ReentrantLock();
|
|
61
|
+
lock.lock();
|
|
62
|
+
try {
|
|
63
|
+
callBlockingIO();
|
|
64
|
+
} finally {
|
|
65
|
+
lock.unlock();
|
|
66
|
+
}
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
---
|
|
70
|
+
|
|
71
|
+
## Pattern Matching for instanceof (JEP 394)
|
|
72
|
+
|
|
73
|
+
```java
|
|
74
|
+
// Before Java 16
|
|
75
|
+
if (obj instanceof String) {
|
|
76
|
+
String s = (String) obj;
|
|
77
|
+
return s.length();
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
// Java 21
|
|
81
|
+
if (obj instanceof String s) {
|
|
82
|
+
return s.length();
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
// With guard
|
|
86
|
+
if (obj instanceof String s && !s.isEmpty()) {
|
|
87
|
+
return s.toUpperCase();
|
|
88
|
+
}
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
---
|
|
92
|
+
|
|
93
|
+
## Pattern Matching for switch (JEP 441)
|
|
94
|
+
|
|
95
|
+
```java
|
|
96
|
+
// Type patterns
|
|
97
|
+
String format = switch (obj) {
|
|
98
|
+
case Integer i -> String.format("int %d", i);
|
|
99
|
+
case Double d -> String.format("double %.2f", d);
|
|
100
|
+
case String s -> String.format("String '%s'", s);
|
|
101
|
+
case null -> "null value";
|
|
102
|
+
default -> obj.toString();
|
|
103
|
+
};
|
|
104
|
+
|
|
105
|
+
// Guarded patterns (when clause)
|
|
106
|
+
String classify = switch (number) {
|
|
107
|
+
case Integer i when i < 0 -> "negative";
|
|
108
|
+
case Integer i when i == 0 -> "zero";
|
|
109
|
+
case Integer i -> "positive";
|
|
110
|
+
default -> "non-integer";
|
|
111
|
+
};
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
---
|
|
115
|
+
|
|
116
|
+
## Record Classes (JEP 395)
|
|
117
|
+
|
|
118
|
+
Records are immutable data carriers with auto-generated `equals`, `hashCode`, `toString`, and accessors.
|
|
119
|
+
|
|
120
|
+
```java
|
|
121
|
+
// Basic record
|
|
122
|
+
record Point(int x, int y) {}
|
|
123
|
+
|
|
124
|
+
Point p = new Point(3, 4);
|
|
125
|
+
int x = p.x(); // accessor (not getX())
|
|
126
|
+
System.out.println(p); // Point[x=3, y=4]
|
|
127
|
+
|
|
128
|
+
// Compact constructor (validation)
|
|
129
|
+
record Range(int min, int max) {
|
|
130
|
+
Range {
|
|
131
|
+
if (min > max)
|
|
132
|
+
throw new IllegalArgumentException(
|
|
133
|
+
"min %d > max %d".formatted(min, max));
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
// Custom methods
|
|
138
|
+
record Circle(double radius) {
|
|
139
|
+
static final double PI = Math.PI;
|
|
140
|
+
|
|
141
|
+
double area() { return PI * radius * radius; }
|
|
142
|
+
|
|
143
|
+
Circle scale(double factor) { return new Circle(radius * factor); }
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
// Implementing interface
|
|
147
|
+
interface Describable { String describe(); }
|
|
148
|
+
record Color(int r, int g, int b) implements Describable {
|
|
149
|
+
public String describe() {
|
|
150
|
+
return "rgb(%d,%d,%d)".formatted(r, g, b);
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
### When to Use Records vs Classes
|
|
156
|
+
|
|
157
|
+
| Use Record | Use Class |
|
|
158
|
+
|------------|-----------|
|
|
159
|
+
| Pure data containers | Entities with mutable state |
|
|
160
|
+
| DTOs, value objects | Domain objects with lifecycle |
|
|
161
|
+
| API response types | Services, repositories |
|
|
162
|
+
| Config/settings | Mutable builders |
|
|
163
|
+
|
|
164
|
+
---
|
|
165
|
+
|
|
166
|
+
## Record Patterns (JEP 440)
|
|
167
|
+
|
|
168
|
+
Deconstruct records directly in `instanceof` and `switch`:
|
|
169
|
+
|
|
170
|
+
```java
|
|
171
|
+
// instanceof deconstruction
|
|
172
|
+
if (obj instanceof Point(int x, int y)) {
|
|
173
|
+
System.out.println("x=" + x + ", y=" + y);
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
// switch deconstruction
|
|
177
|
+
String describe = switch (shape) {
|
|
178
|
+
case Circle(double r) -> "circle r=%.2f".formatted(r);
|
|
179
|
+
case Rectangle(double w, double h) -> "rect %.1fx%.1f".formatted(w, h);
|
|
180
|
+
default -> "unknown";
|
|
181
|
+
};
|
|
182
|
+
|
|
183
|
+
// Nested patterns
|
|
184
|
+
record ColoredPoint(Point point, Color color) {}
|
|
185
|
+
|
|
186
|
+
if (obj instanceof ColoredPoint(Point(int x, int y), Color(int r, int g, int b))) {
|
|
187
|
+
System.out.printf("Colored point at (%d,%d) with rgb(%d,%d,%d)%n",
|
|
188
|
+
x, y, r, g, b);
|
|
189
|
+
}
|
|
190
|
+
```
|
|
191
|
+
|
|
192
|
+
---
|
|
193
|
+
|
|
194
|
+
## Sealed Classes (JEP 409)
|
|
195
|
+
|
|
196
|
+
Sealed classes restrict which classes can implement/extend them, enabling exhaustive pattern matching.
|
|
197
|
+
|
|
198
|
+
```java
|
|
199
|
+
// Sealed interface with records
|
|
200
|
+
sealed interface Shape permits Circle, Rectangle, Triangle {}
|
|
201
|
+
|
|
202
|
+
record Circle(double radius) implements Shape {}
|
|
203
|
+
record Rectangle(double width, double height) implements Shape {}
|
|
204
|
+
record Triangle(double base, double height) implements Shape {}
|
|
205
|
+
|
|
206
|
+
// Exhaustive switch — no default needed
|
|
207
|
+
double area = switch (shape) {
|
|
208
|
+
case Circle(double r) -> Math.PI * r * r;
|
|
209
|
+
case Rectangle(double w, double h) -> w * h;
|
|
210
|
+
case Triangle(double b, double h) -> 0.5 * b * h;
|
|
211
|
+
};
|
|
212
|
+
|
|
213
|
+
// Sealed class hierarchy (non-record)
|
|
214
|
+
sealed class Vehicle permits Car, Truck, Motorcycle {}
|
|
215
|
+
final class Car extends Vehicle { }
|
|
216
|
+
non-sealed class Truck extends Vehicle { } // allows further subclassing
|
|
217
|
+
```
|
|
218
|
+
|
|
219
|
+
### Benefits
|
|
220
|
+
|
|
221
|
+
- Compiler enforces exhaustive handling in `switch`
|
|
222
|
+
- Clear closed type hierarchy in domain model
|
|
223
|
+
- Better than `enum` when subtypes carry different data
|
|
224
|
+
|
|
225
|
+
---
|
|
226
|
+
|
|
227
|
+
## Sequenced Collections (JEP 431)
|
|
228
|
+
|
|
229
|
+
New interfaces: `SequencedCollection`, `SequencedSet`, `SequencedMap`.
|
|
230
|
+
|
|
231
|
+
```java
|
|
232
|
+
// SequencedCollection
|
|
233
|
+
List<String> list = new ArrayList<>(List.of("a", "b", "c"));
|
|
234
|
+
String first = list.getFirst(); // "a"
|
|
235
|
+
String last = list.getLast(); // "c"
|
|
236
|
+
list.addFirst("z"); // ["z", "a", "b", "c"]
|
|
237
|
+
list.addLast("end"); // ["z", "a", "b", "c", "end"]
|
|
238
|
+
list.removeFirst(); // ["a", "b", "c", "end"]
|
|
239
|
+
|
|
240
|
+
// Reversed view (live, backed by original)
|
|
241
|
+
List<String> reversed = list.reversed();
|
|
242
|
+
|
|
243
|
+
// SequencedMap
|
|
244
|
+
LinkedHashMap<String, Integer> map = new LinkedHashMap<>();
|
|
245
|
+
map.put("one", 1);
|
|
246
|
+
map.put("two", 2);
|
|
247
|
+
map.put("three", 3);
|
|
248
|
+
|
|
249
|
+
Map.Entry<String, Integer> first = map.firstEntry(); // "one"=1
|
|
250
|
+
Map.Entry<String, Integer> last = map.lastEntry(); // "three"=3
|
|
251
|
+
map.putFirst("zero", 0); // inserts at front
|
|
252
|
+
SequencedMap<String, Integer> rev = map.reversed();
|
|
253
|
+
```
|
|
254
|
+
|
|
255
|
+
---
|
|
256
|
+
|
|
257
|
+
## Migration from Legacy Java
|
|
258
|
+
|
|
259
|
+
### Replace instanceof chains
|
|
260
|
+
|
|
261
|
+
```java
|
|
262
|
+
// Legacy (avoid)
|
|
263
|
+
if (obj instanceof String) {
|
|
264
|
+
return ((String) obj).length();
|
|
265
|
+
} else if (obj instanceof Integer) {
|
|
266
|
+
return ((Integer) obj).intValue();
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
// Modern
|
|
270
|
+
return switch (obj) {
|
|
271
|
+
case String s -> s.length();
|
|
272
|
+
case Integer i -> i;
|
|
273
|
+
default -> -1;
|
|
274
|
+
};
|
|
275
|
+
```
|
|
276
|
+
|
|
277
|
+
### Replace POJOs with Records
|
|
278
|
+
|
|
279
|
+
```java
|
|
280
|
+
// Legacy POJO (avoid for pure data)
|
|
281
|
+
public class Point {
|
|
282
|
+
private final int x, y;
|
|
283
|
+
public Point(int x, int y) { this.x = x; this.y = y; }
|
|
284
|
+
public int getX() { return x; }
|
|
285
|
+
public int getY() { return y; }
|
|
286
|
+
@Override public boolean equals(Object o) { ... }
|
|
287
|
+
@Override public int hashCode() { ... }
|
|
288
|
+
@Override public String toString() { ... }
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
// Modern Record
|
|
292
|
+
record Point(int x, int y) {}
|
|
293
|
+
```
|
|
294
|
+
|
|
295
|
+
### Replace thread pools for I/O with Virtual Threads
|
|
296
|
+
|
|
297
|
+
```java
|
|
298
|
+
// Legacy (avoid for I/O-bound)
|
|
299
|
+
ExecutorService pool = Executors.newFixedThreadPool(200);
|
|
300
|
+
|
|
301
|
+
// Modern
|
|
302
|
+
ExecutorService pool = Executors.newVirtualThreadPerTaskExecutor();
|
|
303
|
+
```
|
package/templates/manifest.json
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
{
|
|
2
|
-
"version": "0.
|
|
2
|
+
"version": "0.31.0",
|
|
3
3
|
"lastUpdated": "2026-03-09T00:00:00.000Z",
|
|
4
4
|
"components": [
|
|
5
5
|
{
|
|
@@ -24,7 +24,7 @@
|
|
|
24
24
|
"name": "guides",
|
|
25
25
|
"path": "guides",
|
|
26
26
|
"description": "Reference documentation",
|
|
27
|
-
"files":
|
|
27
|
+
"files": 25
|
|
28
28
|
},
|
|
29
29
|
{
|
|
30
30
|
"name": "hooks",
|