<< All versions
Skill v1.0.0
currentAutomated scan100/100lugassawan/swe-workbench/language-java
──Details
PublishedSeptember 27, 2026 at 08:45 PM
Content Hashsha256:73b4a466302753f5...
Git SHA
──Files
Files (1 file, 5.4 KB)
SKILL.md5.4 KBactive
SKILL.md · 131 lines · 5.4 KB
version: "1.0.0" name: language-java description: Java idioms — records, sealed types, virtual threads, and JDK 21+ patterns. Auto-load when working with .java files, pom.xml, build.gradle, or when the user mentions Java, JVM, Spring, Maven, Gradle, sealed classes, or virtual threads.
Java
Records and sealed types
Modern Java models data without boilerplate.
java
record Point(double x, double y) {}sealed interface Shape permits Circle, Rectangle {}record Circle(Point center, double radius) implements Shape {}record Rectangle(Point topLeft, Point bottomRight) implements Shape {}
- Use
recordfor immutable data carriers — equals, hashCode, toString, and accessors for free. sealedcloses a hierarchy; exhaustiveswitchreplacesinstanceofchains.
java
double area = switch (shape) {case Circle c -> Math.PI * c.radius() * c.radius();case Rectangle r -> Math.abs(r.bottomRight().x() - r.topLeft().x())* Math.abs(r.bottomRight().y() - r.topLeft().y());};
Optional and null discipline
- Return
Optional<T>from methods that may have no result; never use it as a field or parameter type. Optionalis not a null check replacement — it signals "absence is a valid outcome."- Annotate parameters and fields with
@NonNull/@Nullablefor static analysis. - Jackson populates
List<T>with literal nulls from valid JSON ({"content":[null]}) regardless
of declared nullability — filter before mapping over an externally-deserialized collection, or drop them at the boundary with @JsonSetter(contentNulls = Nulls.SKIP).
java
Optional<User> find(String id) { ... }find(id).map(User::email).orElseThrow(() -> new NotFoundException(id));List<String> ids = payload.content().stream().filter(Objects::nonNull).map(Content::id).toList();
Concurrency — virtual threads (JDK 21+)
Virtual threads (Project Loom) make blocking-style IO safe at scale.
java
try (var scope = new StructuredTaskScope.ShutdownOnFailure()) {Future<User> user = scope.fork(() -> fetchUser(id));Future<Order> order = scope.fork(() -> fetchOrder(orderId));scope.join().throwIfFailed();return new Response(user.get(), order.get());}
Executors.newVirtualThreadPerTaskExecutor()— drop-in fornewCachedThreadPool()with virtual-thread semantics.- Do not pool virtual threads; create-per-task is the idiom.
- Watch for carrier-thread pinning:
synchronizedblocks and some native calls pin a virtual thread to its carrier. PreferReentrantLockwhen high-throughput blocking is expected. StructuredTaskScope(JDK 21–24 preview — not yet standard; enable with--enable-preview) enforces structured concurrency: tasks are joined before the scope exits.
Error handling
- Prefer unchecked exceptions at boundaries; translate checked exceptions from libraries early.
try-with-resourcesfor anythingAutoCloseable— never close in afinallyblock manually.- Exception translation: catch a library-specific exception at the boundary, rethrow as your domain exception.
java
try (var conn = dataSource.getConnection()) {// ...} catch (SQLException e) {throw new RepositoryException("fetch user " + id, e);}
Streams and collections
Streamfor transformations; avoid imperative loops when a pipeline is clearer..toList()(JDK 16+) overCollectors.toList()— returns an unmodifiable list.- Use
List.of,Map.of,Set.offor small immutable collections;Map.copyOfto defensively copy. - Externally-deserialized sources may hold null elements — see Optional and null discipline.
java
List<String> emails = users.stream().filter(User::isActive).map(User::email).toList();
Doc comments
- javadoc — the first sentence is the summary shown in generated indexes; keep it a single fragment, not a paragraph.
- Add
@param/@returnonly when they convey something the signature doesn't (units, ownership, valid ranges).
java
/** Returns the user's active orders, most recent first. */List<Order> activeOrders(String userId) { ... }
Build and packaging
- Maven:
pom.xmlwith<dependencyManagement>for BOM imports; prefer the wrapper (./mvnw). - Gradle:
build.gradle(Groovy) orbuild.gradle.kts(Kotlin DSL — preferred for IDE support). - JPMS (
module-info.java): adopt only when publishing a library that needs strong encapsulation.
Tooling
- Imports/Format:
mvn spotless:apply/./gradlew spotlessApply - Lint:
mvn checkstyle:check/./gradlew checkstyleMain - Test:
mvn test/./gradlew test(see Testing below)
Testing
- JUnit 5 (
@Test,@ParameterizedTest,@MethodSource) — not JUnit 4. - AssertJ for fluent assertions:
assertThat(actual).isEqualTo(expected). - Mockito for external boundaries; do not mock domain objects.
java
@ParameterizedTest@MethodSource("provideInputs")void computesTax(double income, double expectedTax) {assertThat(TaxCalculator.compute(income)).isCloseTo(expectedTax, within(0.01));}
Avoid
- Raw types (
Listinstead ofList<String>). - Returning or passing
nullwhereOptionalor a sentinel value communicates intent. - Mutable
staticstate outside of intentional singletons. equalswithout a matchinghashCodeoverride.- Blocking inside a reactive pipeline or
CompletableFuturechain. - Trusting a declared non-null element type on a Jackson-deserialized collection.