java-programmer skill
Java 툴링, 문서화 표준, 테스트 관행 및 현대적인 JVM 관용구에 대한 가이드를 제공합니다.
- GitHub 스타
- 9
- 파일
- 2
- 마지막 커밋
- 2026년 10월 13일
- 라이선스
- EPL-2.0
- 허용된 도구
- —
java-programmer skill은 무엇을 하나요?
java-programmer은(는) agent skill입니다. Java 툴링, 문서화 표준, 테스트 관행 및 현대적인 JVM 관용구에 대한 가이드를 제공합니다.
skill의 SKILL.md에서 생성된 요약입니다.
java-programmer skill 정보
Java 기반 프로젝트나 JVM 생태계에서 작업하는 개발자는 이 SKILL을 사용하여 현대적인 코딩 표준 및 툴링에 대한 가이드를 받을 수 있습니다. 빌드 도구, 테스트 프레임워크, 의존성 관련 의사결정을 지원하며 Javadoc 및 JUnit 테스트 작성 방향을 제시합니다. 이 SKILL은 코드가 유지보수 가능하고 표현력이 풍부하게 유지되도록 함수형 프로그래밍 패턴과 현대적인 Java 관용구를 적용하는 데 중점을 둡니다.
에이전트가 이 SKILL을 로드하면 Checker Framework와 JSpecify 어노테이션을 사용하여 엄격한 컴파일 타임 검증을 구현하도록 도울 수 있습니다. 코드 포맷팅을 위한 Spotless 및 스타일 강제를 위한 Checkstyle과 같은 도구 사용에 대한 구체적인 지침을 제공합니다. 또한 records, sealed classes, virtual threads와 같은 기능을 활용하기 위해 최신 Java LTS 버전을 사용하는 것을 강조합니다. 아울러 본인이 소유한 프로젝트에서는 새로운 기능을 적극적으로 도입하되, 서드파티 코드베이스의 기존 컨벤션을 존중하는 방법도 안내합니다.
agent가 수행할 수 있는 작업
- 1컴파일 타임 안정성 구현Checker Framework와 JSpecify 어노테이션을 구성하여 NullPointerException 및 기타 런타임 에러를 방지합니다.
- 2Java 코드베이스 현대화기존 프로젝트를 records, sealed classes, pattern matching과 같은 현대적인 기능을 사용하도록 리팩터링합니다.
- 3프로젝트 툴링 표준 수립포맷팅을 위한 Spotless와 스타일 강제를 위한 Checkstyle을 포함한 필수 툴링 스택을 설정합니다.
- 4서드파티 기여 가이드오픈 소스 프로젝트에 기여할 때 확립된 컨벤션과 타겟 버전을 준수합니다.
skill의 SKILL.md를 기반으로 작성되었습니다. 모든 사용 사례는 해당 문서의 인용구와 대조 확인되었습니다.
java-programmer skill 설치 방법
각 명령은 skill 폴더를 클라이언트의 skills 디렉터리에 복사합니다. 클라이언트를 재시작하거나 새 세션을 시작하여 로드하세요.플러그인에 java-programmer skill 설치
/plugin marketplace add Pyroxin/opinionated-claude-skills /plugin install opinionated-java-ecosystem@opinionated-claude-skills
Claude Code에 java-programmer skill 설치
~/.claude/skills/java-programmer/SKILL.md
$ npx degit Pyroxin/opinionated-claude-skills/opinionated-java-ecosystem/skills/java-programmer ~/.claude/skills/java-programmerClaude Code (project)에 java-programmer skill 설치
.claude/skills/java-programmer/SKILL.md
$ npx degit Pyroxin/opinionated-claude-skills/opinionated-java-ecosystem/skills/java-programmer .claude/skills/java-programmerCodex에 java-programmer skill 설치
~/.agents/skills/java-programmer/SKILL.md
$ npx degit Pyroxin/opinionated-claude-skills/opinionated-java-ecosystem/skills/java-programmer ~/.agents/skills/java-programmerGemini CLI에 java-programmer skill 설치
~/.gemini/skills/java-programmer/SKILL.md
$ npx degit Pyroxin/opinionated-claude-skills/opinionated-java-ecosystem/skills/java-programmer ~/.gemini/skills/java-programmerClaude.ai에 java-programmer skill 설치
npx degit Pyroxin/opinionated-claude-skills/opinionated-java-ecosystem/skills/java-programmer java-programmer && zip -r java-programmer.zip java-programmer # claude.ai → Customize → Skills → + → Create skill → Upload a skill → java-programmer.zip
SKILL.md
GitHub에서 보기Java Programmer
Purpose
This skill provides guidance on Java-specific tooling, documentation standards, testing practices, and modern Java idioms. Java is a statically-typed, object-oriented language with a massive ecosystem and strong backwards compatibility guarantees. This skill focuses on navigating the Java ecosystem effectively, writing maintainable Java code, and applying functional programming concepts within Java's constraints.
When to Use This Skill
Use this skill when:
- Working with Java codebases (any version, but especially Java 8+)
- Making decisions about build tools, testing frameworks, or dependencies
- Writing Javadoc documentation
- Writing JUnit tests
- Applying functional programming patterns in Java
- Navigating the JVM ecosystem (choosing between JVM languages)
<core_philosophy>
Core Philosophy
For foundational software engineering principles, see the software-engineer skill. For OOP principles (SOLID, GoF patterns), see the object-oriented-programmer skill.
Java's Strengths and Constraints
Java excels in specific contexts but has limitations compared to more modern languages.
Where Java shines:
- Enterprise systems — Mature ecosystem, strong tooling, extensive libraries
- Team stability — Explicit types, verbose code, fewer "clever" tricks
- Long-term maintenance — Backwards compatibility, gradual evolution
- JVM ecosystem — Interop with Kotlin, Scala, Clojure, Groovy
- Performance — JIT compilation, mature garbage collectors, profiling tools
Where Java struggles:
- Rapid prototyping — Verbosity slows iteration
- Functional programming — Retrofitted features, verbose syntax
- Type system — Lacks algebraic data types, pattern matching (until recent versions)
- Ceremony — Boilerplate reduces signal-to-noise ratio
Staff insight: If you're writing Java professionally but prefer functional languages, focus on using modern Java features (streams, Optional, lambdas) to bring functional thinking into Java's constraints. Don't fight the language—work within its idioms.
Documentation as Contract
Javadoc is more than comments—it's a contract between API and client. Treat it as seriously as the code itself.
Quote to remember: "Code is read more often than written." — Guido van Rossum. Documentation is read even more often than that. </core_philosophy>
<type_annotations>
Type Annotations and The Checker Framework Are Mandatory
Java's type system lacks many important guarantees. Type annotations with The Checker Framework enable compile-time verification of properties that the type system doesn't enforce.
Why type annotations and static analysis matter:
- Critical for LLM-assisted development — Explicit contracts enable better code generation and reasoning
- Eliminate entire classes of errors at compile time (NullPointerException, regex errors, format string bugs)
- Make API contracts machine-readable (not just documented in Javadoc)
- Enable static analysis to catch bugs before runtime
- Self-documenting code (contracts visible in signatures)
The Checker Framework is mandatory for all new projects:
- Use JSpecify annotations for nullness (
@Nullable,@NonNullvia defaults) - JSpecify provides multi-tool compatibility (works with Checker Framework, IntelliJ, NullAway, etc.)
- Enable as many Checker Framework checkers as practical:
- Nullness Checker (via JSpecify annotations) — Prevent NullPointerException
- Optional Checker — Enforce proper Optional usage
- Regex Checker — Verify regex string validity at compile time
- Format String Checker — Verify printf/format string correctness
- Interning Checker — Ensure string interning correctness
- Index Checker — Prevent array bounds errors
- Lock Checker — Verify lock usage and prevent race conditions
- Additional checkers as applicable to domain
Example with JSpecify nullness annotations:
import org.jspecify.annotations.Nullable;
// @NonNull is the default assumption (no annotation needed)
public class UserService {
/**
* Finds user by ID.
*
* @param id the user ID (must not be null, default assumption)
* @return user if found, null otherwise
*/
public @Nullable User findById(String id) {
// Checker verifies: id cannot be null (default @NonNull)
// Checker requires: callers handle possible null return
return repository.findById(id).orElse(null);
}
/**
* Gets user display name.
*
* @param user the user (must not be null, default assumption)
* @return display name (never null, default assumption)
*/
public String getDisplayName(User user) {
// Checker verifies: user cannot be null
// Checker enforces: return value cannot be null
String name = user.getName();
return name != null ? name : "Guest";
}
}
Example with other Checker Framework annotations:
import org.checkerframework.checker.regex.qual.Regex;
import org.checkerframework.checker.formatter.qual.FormatMethod;
public class ValidationService {
/**
* Validates input against pattern.
*
* @param input the input string
* @param pattern the regex pattern (verified at compile time)
* @return true if input matches pattern
*/
public boolean matches(String input, @Regex String pattern) {
// Checker verifies: pattern is valid regex at compile time
return input.matches(pattern);
}
/**
* Logs formatted message.
*
* @param format the format string (verified at compile time)
* @param args the format arguments
*/
@FormatMethod
public void logFormatted(String format, Object... args) {
// Checker verifies: format string matches args at compile time
logger.info(String.format(format, args));
}
}
When to use annotations:
- Nullness (JSpecify):
- Mark
@Nullableexplicitly when null is permitted - Default assumption is
@NonNull(no annotation needed) - Annotate parameters, return types, fields, generic type arguments
- Mark
- Other Checker Framework annotations:
- Use
@Regexfor all regex pattern strings - Use
@FormatMethodand format string annotations for printf-style methods - Use
@GuardedByfor fields accessed under locks - Use domain-specific checkers as applicable
- Use
Why both type annotations AND Javadoc:
- Type annotations: Machine-readable contracts (compiler enforces)
- Javadoc: Human-readable context (explains why, when, edge cases)
- Example: Annotation says
@Nullable, Javadoc explains when null is returned
Maven/Gradle configuration:
<!-- Maven: Add Checker Framework -->
<dependency>
<groupId>org.checkerframework</groupId>
<artifactId>checker-qual</artifactId>
<version>3.42.0</version>
</dependency>
<dependency>
<groupId>org.jspecify</groupId>
<artifactId>jspecify</artifactId>
<version>1.0.0</version>
</dependency>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<compilerArgs>
<arg>-Xplugin:ErrorProne</arg>
<arg>-J--add-exports=jdk.compiler/com.sun.tools.javac.api=ALL-UNNAMED</arg>
<arg>-J--add-exports=jdk.compiler/com.sun.tools.javac.code=ALL-UNNAMED</arg>
<arg>-Xplugin:checkerframework -processor org.checkerframework.checker.nullness.NullnessChecker,org.checkerframework.checker.regex.RegexChecker,org.checkerframework.checker.formatter.FormatterChecker</arg>
</compilerArgs>
</configuration>
</plugin>
CI/CD integration:
- All Checker Framework checkers must run in CI/CD pipeline
- Builds fail on checker errors (no warnings mode)
- No exceptions for "I'll fix it later"
Staff insight: The Checker Framework is as important as comprehensive testing for code quality. JSpecify annotations provide nullness checking with multi-tool compatibility. Beyond nullness, use all applicable checkers (Regex, Format String, Index, Lock, etc.) to catch errors at compile time. Type annotations provide compile-time verification that tests and documentation cannot. </type_annotations>
<version_targeting>
Java Version Targeting: Use Latest Version Only
All new Java projects must target the latest Java version or at least the latest LTS version. (Java 25 is the latest LTS release as of late 2025). You can find the latest version by reading this Wikipedia article. That article is also a good reference for new features you should look at adopting.
Why Java 25+:
- Sealed classes — Algebraic data types for eliminating invalid states
- Pattern matching — Type-safe destructuring (for instanceof, switch expressions)
- Records — Concise immutable data carriers
- Text blocks — Readable multi-line strings
- Virtual threads — Lightweight concurrency (Project Loom)
- Modern APIs — Collections.of(), Stream improvements, enhanced switch
- LTS support — Long-term support and security updates
For existing projects:
- Upgrade to Java 25+ as soon as practical
- Aggressively refactor and rewrite to use modern features (records, sealed classes, pattern matching)
- Don't maintain Java 8/11/17 projects indefinitely
- Use upgrades as opportunities to improve project design if possible.
Staff insight: Aggressive adoption of Java features is a philosophy. Java 25 has the features that make Java competitive with modern languages (sealed classes, pattern matching, records). Using older versions means missing critical type safety and expressiveness improvements. Upgrade aggressively.
Respecting Third-Party Codebases
The aggressive adoption philosophy applies ONLY to codebases you own.
When contributing to open source projects or third-party codebases:
- Respect the project's existing style and conventions
- Do not introduce new Java features unless the project explicitly targets that version
- Do not refactor existing code to use modern idioms unless requested
- Follow the project's contribution guidelines strictly
- Match the existing code style, even if it differs from your preferences
Why this matters:
- Stability — OSS projects prioritize stability over bleeding-edge features
- Community consensus — Style changes require community agreement
- Compatibility — Projects may target older Java versions for user compatibility
- Maintainability — Consistency matters more than modernization in large codebases
When you can suggest modernization:
- File an issue proposing Java version upgrade with justification
- Propose style changes through project governance process
- Offer to help with migration if project agrees
- Never surprise maintainers with unsolicited rewrites
Staff insight: Your aggressive adoption philosophy is for codebases you control. When contributing to others' projects, you're a guest—respect the house rules. Propose improvements through proper channels, don't impose them through pull requests. Stability and community consensus matter more than your personal preferences in shared codebases. </version_targeting>
<tooling_stack>
Mandatory Tooling Stack
All new Java projects must use the following tools with CI/CD integration. Builds must fail on violations.
Required tools:
Spotless (code formatting):
- Enforces consistent formatting automatically
- Eliminates formatting debates
- Supports Google Java Format, Palantir, Eclipse formatters
- Runs during build, fails on violations
- Use for: All new projects (no exceptions)
Checkstyle (code style enforcement):
- Enforces coding standards beyond formatting
- Checks naming conventions, javadoc presence, complexity
- Use Checkstyle for semantic rules, Spotless for formatting
- Configuration files available in
./assets/checkstyle.xml - Use for: All new projects (no exceptions)
SpotBugs (static analysis for bugs):
- Detects common bug patterns (resource leaks, null dereferences, concurrency issues)
- Successor to FindBugs
- Must run in CI/CD pipeline
- Use for: All new projects (no exceptions)
ErrorProne (Google's bug pattern checker):
- Catches Java-specific bugs at compile time
- More sophisticated than SpotBugs (understands Java semantics deeply)
- Integrates into javac compilation
- Use for: All new projects (no exceptions)
JaCoCo (code coverage):
- Measures test coverage
- Enforces minimum coverage thresholds in CI/CD
- Use for: All projects with test suites
JSpecify + Checker Framework (type annotations):
- Already covered above
- Nullness checker via JSpecify
- Additional checkers (Regex, Format String, Index, Lock)
Maven/Gradle configuration example:
<!-- Maven pom.xml -->
<build>
<plugins>
<!-- Spotless for formatting -->
<plugin>
<groupId>com.diffplug.spotless</groupId>
<artifactId>spotless-maven-plugin</artifactId>
<version>2.43.0</version>
<configuration>
<java>
<googleJavaFormat>
<version>1.19.1</version>
<style>GOOGLE</style>
</googleJavaFormat>
<removeUnusedImports />
<formatAnnotations />
</java>
</configuration>
<executions>
<execution>
<goals>
<goal>check</goal>
</goals>
<phase>verify</phase>
</execution>
</executions>
</plugin>
<!-- Checkstyle -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-checkstyle-plugin</artifactId>
<version>3.3.1</version>
<configuration>
<configLocation>checkstyle.xml</configLocation>
<consoleOutput>true</consoleOutput>
<failsOnError>true</failsOnError>
</configuration>
<executions>
<execution>
<goals>
<goal>check</goal>
</goals>
<phase>verify</phase>
</execution>
</executions>
</plugin>
<!-- SpotBugs -->
<plugin>
<groupId>com.github.spotbugs</groupId>
<artifactId>spotbugs-maven-plugin</artifactId>
<version>4.8.3.0</version>
<configuration>
<effort>Max</effort>
<threshold>Low</threshold>
<failOnError>true</failOnError>
</configuration>
<executions>
<execution>
<goals>
<goal>check</goal>
</goals>
<phase>verify</phase>
</execution>
</executions>
</plugin>
<!-- ErrorProne -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.12.1</version>
<configuration>
<release>25</release>
<compilerArgs>
<arg>-XDcompilePolicy=simple</arg>
<arg>-Xplugin:ErrorProne</arg>
</compilerArgs>
<annotationProcessorPaths>
<path>
<groupId>com.google.errorprone</groupId>
<artifactId>error_prone_core</artifactId>
<version>2.24.1</version>
</path>
</annotationProcessorPaths>
</configuration>
</plugin>
<!-- JaCoCo -->
<plugin>
<groupId>org.jacoco</groupId>
<artifactId>jacoco-maven-plugin</artifactId>
<version>0.8.11</version>
<executions>
<execution>
<goals>
<goal>prepare-agent</goal>
</goals>
</execution>
<execution>
<id>check</id>
<goals>
<goal>check</goal>
</goals>
<configuration>
<rules>
<rule>
<element>PACKAGE</element>
<limits>
<limit>
<counter>LINE</counter>
<value>COVEREDRATIO</value>
<minimum>0.80</minimum>
</limit>
</limits>
</rule>
</rules>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
CI/CD integration:
- All tools must run in CI/CD pipeline (GitHub Actions, GitLab CI, Jenkins, etc.)
- Builds fail on any tool violations (no warnings mode)
- No exceptions for "I'll fix it later"
- Formatting (Spotless), style (Checkstyle), bugs (SpotBugs, ErrorProne), coverage (JaCoCo) all must pass
Configuration files:
- Example Checkstyle configuration:
./assets/checkstyle.xml(reference this in your pom.xml/build.gradle) - Customize as needed but maintain strict standards
- Share configurations across projects for consistency
Staff insight: Don't waste time debating formatting or choosing between tools. Use Spotless for formatting (automatic, no configuration needed), Checkstyle for semantic rules, SpotBugs + ErrorProne for bug detection, JaCoCo for coverage. These tools are mandatory, not optional. They catch errors early and enforce consistency. </tooling_stack>
The Java Platform Module System (JPMS) should be used aggressively for new projects, but pragmatism is required due to ecosystem limitations.
When to use JPMS:
- New projects (default choice)
- Multi-module builds where encapsulation matters
- Libraries that want strong encapsulation
- Projects where you control all dependencies
Why JPMS matters:
- Strong encapsulation — Internal packages truly hidden (not just convention)
- Explicit dependencies — module-info.java declares dependencies
- Compile-time verification — Module system verifies dependencies
- Better tooling — jlink for custom runtime images
Basic module-info.java example:
module com.example.myapp {
requires java.sql;
requires com.google.common; // Guava
requires org.slf4j; // SLF4J
exports com.example.myapp.api; // Public API
// Internal packages not exported (truly encapsulated)
}
The pragmatic problem: Third-party library adoption
Many third-party libraries don't have proper module descriptors. This creates friction.
Solutions for mixing modularized and non-modularized code:
1. Automatic modules (non-modularized JARs on module path):
- Put non-modularized JAR on module path
- Becomes "automatic module" with derived name from JAR filename
- Exports all packages, reads all modules
- Works but fragile (module name derived from filename can change)
module com.example.myapp {
requires commons.lang3; // Automatic module (from commons-lang3-3.x.jar)
}
2. Use --add-reads, --add-exports, --add-opens for opening up modules:
java --add-reads com.example.myapp=ALL-UNNAMED \
--add-exports java.base/sun.security.x509=ALL-UNNAMED \
--add-opens java.base/java.lang=ALL-UNNAMED \
-jar myapp.jar
--add-reads— Allows module to read unnamed module (classpath)--add-exports— Export internal JDK packages to your code--add-opens— Allow reflective access to internal packages
3. Split packages problem (fatal in JPMS):
- Two modules cannot contain the same package
- If two dependencies have same package, JPMS fails
- Solution: Relocate packages (Maven Shade plugin) or abandon JPMS for that project
4. When to pragmatically abandon JPMS:
- Too many dependencies lack module descriptors
- Split package conflicts that can't be resolved
- Framework requires classpath (some older frameworks)
- Reflection-heavy code that fights JPMS encapsulation
Don't force JPMS when it creates more problems than it solves.
Practical approach:
- Start with JPMS (aggressive adoption philosophy)
- Use automatic modules for well-behaved non-modularized dependencies
- Use --add-reads/--add-exports flags for problematic cases
- If you hit split packages or too many problematic deps, switch to classpath
- Revisit JPMS periodically as ecosystem improves
Staff insight: JPMS is excellent when it works (strong encapsulation, explicit dependencies) but the Java ecosystem hasn't fully adopted it. Start with JPMS, be prepared to fall back to classpath if third-party libraries cause too much pain. This is pragmatism, not failure—sometimes the tooling isn't ready for your philosophy.
Comprehensive Javadoc documentation is not optional. Every public element must be documented.
When to Write Javadoc
Always document (required for all production code):
- Public APIs (classes, interfaces, methods, fields)
- Package-level documentation (package-info.java)
- Non-obvious design decisions
- Preconditions, postconditions, invariants
- Thread safety guarantees
- Null handling contracts (explain when null is valid, even with annotations)
Document private elements when:
- Logic is non-obvious
- Future maintainers need context
- Design rationale should be preserved
- Usage patterns aren't clear from signature
Every test must have Javadoc:
- What behavior/requirement is being verified
- Why the test exists
- Special test data setup
- Known limitations
Staff insight: Junior developers under-document. Senior developers document the "why" and constraints, not just the "what." Assume future readers (including LLMs) need to understand intent, not just implementation. Comprehensive Javadoc is as important as comprehensive tests.
Javadoc Formatting Standards
HTML, not Markdown:
- Use
<ul>and<li>for lists (NOT Markdown bullets) - Use
<p>for paragraph breaks (with newline before tag) - Use
<code>and{@code}for inline code - Use
<pre>for code blocks - Use
{@link}for references to other types/methods
Example:
/**
* Processes user input and validates against business rules.
* <p>
* This method performs the following steps:
* <ul>
* <li>Sanitizes input to remove malicious content</li>
* <li>Validates against {@link ValidationRule} set</li>
* <li>Returns {@link Result} containing validated data or errors</li>
* </ul>
* <p>
* Thread safety: This method is thread-safe and can be called concurrently.
*
* @param input the user input to process (must not be null)
* @param rules the validation rules to apply
* @return validation result containing either data or errors
* @throws IllegalArgumentException if input is null
*/
public Result<Data> processInput(String input, Set<ValidationRule> rules) {
// implementation
}
이 스킬의 파일
2java-programmer skill 질문
Claude Code에 java-programmer skill을 어떻게 설치하나요?
npx degit Pyroxin/opinionated-claude-skills/opinionated-java-ecosystem/skills/java-programmer ~/.claude/skills/java-programmer를 실행합니다. Claude Code는 ~/.claude/skills(모든 프로젝트) 또는 .claude/skills(한 프로젝트)에서 skills를 로드하며, 설명이 작업과 일치할 때 skill을 사용합니다.
java-programmer skill을 사용할 수 있는 클라이언트는 무엇인가요?
Agent Skills 형식을 읽는 모든 클라이언트(Claude Code, Codex, Gemini CLI, claude.ai(ZIP으로 업로드))가 사용할 수 있습니다. skill 내 스크립트는 클라이언트가 코드 실행을 허용하는 경우에만 실행됩니다.
Java에서 nullness 어노테이션으로 무엇을 사용해야 하나요?
@Nullable과 같은 JSpecify 어노테이션을 사용해야 합니다. 이는 Checker Framework 및 IntelliJ와 멀티 툴 호환성을 제공합니다.
새 프로젝트에서 Java 버전을 어떻게 관리해야 하나요?
모든 새 Java 프로젝트는 sealed classes, records, virtual threads와 같은 기능을 활용할 수 있도록 최신 Java 버전 또는 최소한 최신 LTS 버전을 타겟으로 해야 합니다.
서드파티 코드베이스에서 현대적인 Java 기능을 사용하는 것은 언제 적절한가요?
본인이 소유한 코드베이스에서만 현대적인 기능을 사용해야 합니다. 서드파티 프로젝트에 기여할 때는 기존 스타일과 타겟 버전을 준수해야 합니다.