
Description
Java 17–25 policy and pitfalls. Use when writing, reviewing, or refactoring Java code — enforces idioms around records, sealed types, switch exhaustiveness, Optional, virtual threads, and null-safety that LLMs frequently get wrong.
SKILL.md
Java — policy & pitfalls
Baseline knowledge of the Java language (records, sealed, pattern matching, text blocks, streams, var, generics, Optional API) is assumed — this skill does not teach the language. It encodes the project policy and the traps that keep appearing in code review.
Setup Check (run first)
Before writing non-trivial code, verify:
- JDK version —
java --version, and target version inpom.xml(<maven.compiler.release>) orbuild.gradle(.kts)(java { toolchain { languageVersion = JavaLanguageVersion.of(21) } }). Adjust feature use if < 17. Current LTS: Java 25 (released Sept 2025); Java 21 is the previous LTS. Prefer LTS releases for new projects. - Build tool wrapper — use
./mvnw/./gradlew, never a globally installedmvn/gradle. - Lombok — look for
lombokin dependencies. If present, prefer@RequiredArgsConstructor/@Slf4j/@Builder; if absent, do not introduce Lombok unless asked. - Static analysis —
error-prone,checkstyle,spotbugs,pmd. Respect existing rules; do not add new violations. - Preview features — if build uses
--enable-preview, some features behave differently. Check flag before relying on preview syntax.
MUST DO
Optionalis a return type only. Never a parameter, field, or element of a collection.- Value classes →
record. DTOs, events, results, config snapshots. Not JPA entities (records are final and have no no-arg constructor). - Closed hierarchies →
sealed+ exhaustiveswitch. Compiler catches new cases. switchexpression overif / else ifchains. Pattern-matchingswitchoverinstanceofchains.- Fields
finalunless you have a reason to reassign. - Fail fast at boundaries —
Objects.requireNonNullin public-API constructors; validate invariants in record compact constructors. try-with-resourcesfor anythingAutoCloseable— includingExecutorService(Java 19+).- Virtual threads for blocking I/O (
Executors.newVirtualThreadPerTaskExecutor()). Not for CPU-bound work. - Structured concurrency for multi-call fan-out:
try (var scope = new StructuredTaskScope.ShutdownOnFailure()) { ... }. - Parameterized logging:
log.info("user_updated userId={} status={}", id, status).
MUST NOT DO
- No
Optional.get()without priorisPresent()— use.map(...).orElseThrow(...)or.orElse(default). - No raw types (
Listinstead ofList<Foo>), no@SuppressWarnings("rawtypes")to silence warnings. - No returning
nullfrom a collection-returning method. ReturnList.of()/Collections.emptyList(). - No checked exceptions leaking into
Stream/ lambda. Wrap into an unchecked domain exception at the boundary. - No catching
Exception/Throwableto "make the compiler happy". Handle a specific type or propagate. - No mutating input collections. Make a defensive copy:
List.copyOf(input). - No
synchronizedaround a blocking call on a virtual thread — it pins the carrier thread. UseReentrantLock. - No
Thread.sleep/ blocking I/O onparallelStream()— shared common pool, starves other work. - No mutation of
Stream.toList()result — it's unmodifiable (JDK 16+). - No PII / tokens / raw passwords in logs.
Reference Guide
| Load when | File |
|---|---|
| Debugging subtle language / API behavior (Optional, Stream, switch, records, generics) | references/pitfalls.md |
| Records, sealed hierarchies, pattern-matching switch, preview features (pitfalls & traps, not syntax tutorials) | references/modern-java.md |
Writing concurrent code (virtual threads, structured concurrency, ExecutorService lifecycle, ThreadLocal traps) | references/concurrency.md |
| File / stream / socket I/O, charsets, partial reads, NIO buffers | references/io.md |
Output Format
When producing code:
- A short plan (1–3 bullets) of what's changing.
- The code.
- A checklist of the non-obvious MUST rules applied.
When reviewing code: call out MUST-DO / MUST-NOT violations explicitly and suggest the minimal fix.
More skills from the junie-extensions repository
View all 9 skillsandroid
build Android applications with Kotlin
Jul 13AndroidEngineeringKotlinMobilecontext7
search library and framework documentation
Jul 17DocumentationMCPReferencekotlin-engineer
write and refactor Kotlin code
Jul 13Code ReviewEngineeringKotlinlaravel-engineer
build and architect Laravel applications
Jul 13BackendEngineeringLaravelPHPphp-engineer
write and refactor modern PHP code
Jul 13Code AnalysisEngineeringPHPredis-best-practices
implement Redis best practices
Jul 13DatabaseEngineeringPerformanceRedis
More from JetBrains
View publishermps-aspect-accessories
configure JetBrains MPS module dependencies
MPS
Jul 17ArchitectureConfigurationEngineeringmps-aspect-actions
define and edit MPS node factories
MPS
Jul 17ArchitectureEngineeringmps-aspect-behavior
define and edit MPS concept behavior
MPS
Jul 13ArchitectureEngineeringmps-aspect-constraints
define JetBrains MPS language constraints
MPS
Jul 23ArchitectureCode Analysismps-aspect-dataflow
define and debug MPS dataflow builders
MPS
Jul 13Data Analysismps-aspect-editor
define MPS editor layouts
MPS
Jul 23DesignUI Components