Skills DirectorySkills Directory
SkillsLearnSecurityCategoriesDocsCommunityBlog
Sign InSubmit Skill
Skills Directory

Security-tested agent skills for Claude, coding agents, and AI workflows.

Directory

  • Browse Skills
  • All Skills A–Z
  • Claude Skills
  • Claude Code Skills
  • Agent Skills
  • Categories
  • Submit a Skill

Learn

  • Learn Hub
  • Install Claude Skills
  • Write SKILL.md
  • Skills vs MCP
  • Directories Compared

Security

  • Security
  • Methodology
  • Secure Claude Skills
  • Security Badges

Company

  • About
  • Community
  • Blog
  • API Docs
  • Advertise

2026 Skills Directory. All rights reserved.

Back to skills

Java Null Safety

ASecurity

Null as a semantic problem, not a syntax problem: what each null means (absence, error, uninitialised), nullability as an API contract, JSpecify @NullMarked and @Nullable, where Objects.requireNonNull belongs, empty collections over null, and the boundaries where null leaks in (deserialisation, ORMs, Map.get, arrays). Use when an NPE surfaces far from its cause, when hardening a service or module boundary, when adopting nullability annotations, or when reviewing constructors and public entry ...

2 stars
0 votes
0 copies
0 views
Added 9/19/2026
developmentrustjavaexpressapidocumentation

Works with

api

Security Analysis

A100/100

Scanned 9/19/2026

Install to Claude Code

$npx -y skills add robsonkades/agent-skills --skill java-null-safety --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Java Null Safety?

Add the live security badge to your README — it updates automatically with every re-scan.

Security grade badge for Java Null Safety
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/robsonkades-java-null-safety/badge)](https://www.skillsdirectory.com/skills/robsonkades-java-null-safety)

More formats (shields.io, HTML) on the badges page.

Download Zip
Files
SKILL.md
---
name: java-null-safety
description: >
  Null as a semantic problem, not a syntax problem: what each null means (absence, error,
  uninitialised), nullability as an API contract, JSpecify @NullMarked and @Nullable, where
  Objects.requireNonNull belongs, empty collections over null, and the boundaries where null
  leaks in (deserialisation, ORMs, Map.get, arrays). Use when an NPE surfaces far from its
  cause, when hardening a service or module boundary, when adopting nullability annotations,
  or when reviewing constructors and public entry points. Does not cover the Optional API —
  orElse/orElseGet, chaining, where Optional belongs — which is java-optional, nor general
  validation strategy at trust boundaries — range and state checks, normalisation — which is
  java-defensive-programming.
---

# Java Null Safety

## Purpose

Turn null from an ambient hazard into a stated contract. Java is not null-safe and JSpecify
annotations add no built-in runtime enforcement — enforcement depends on the actual checker
or runtime validation path. The failure mode this skill prevents is the NPE thrown three layers and
twenty minutes away from the code that produced the null, because nothing between the two
said whether null was allowed.

## Workflow

Inspect compiler release/toolchains, runtime, existing annotation vocabulary, checker scope,
JSpecify/tool versions and mapper configuration before edits. Guidance uses Java 25 and
JSpecify 1.0; collection factories need Java 9+,
`List.copyOf` Java 10+, records and `Stream.toList` Java 16+. Use target-compatible alternatives;
do not upgrade or introduce a checker/dependency unless annotation adoption is in scope.
Reuse established caller and construction-path evidence; ask only about unresolved null meanings
or enforcement paths that change the fix. Keep an adequate existing representation. When tooling
or a construction path is unavailable, report the gap rather than claiming null safety.

1. **Name what each null means.** Absence (no promotion for this SKU), error (mandatory
   field missing), or uninitialised (lifecycle not yet complete). Different meanings get
   different treatments: choose an empty collection, Optional or explicit nullable contract
   for absence; reject invalid input under the operation's failure policy; document or remove
   an uninitialised phase. Preserve distinctions such as missing, explicit null and empty when
   callers observe them; do not turn a local fix into an incompatible API migration.
2. **Establish the default.** Preserve the project's annotation vocabulary. When adopting
   JSpecify, `@NullMarked` establishes a non-null default with `@Nullable` exceptions and the
   type-variable/local-inference qualifications in the reference. Unmarked nullness is
   unspecified to JSpecify; inspect documentation and callers before changing the contract.
3. **Enforce where ownership/trust changes.** Constructors establish their own invariants;
   adapters validate external values; public APIs enforce documented non-null preconditions.
   Remove interior checks only when every construction/call path proves the contract.
4. **Fence the leaks.** DTO binding, ORM mappings, `Map.get`, array slots and varargs can
   introduce null under their actual configuration/API contracts. Convert at the owning
   boundary; retain legal nulls and re-check after transitions that can invalidate the proof.
5. **Verify the affected contract.** Exercise null through the changed boundary, asserting
   rejection, normalization or preservation according to its policy. Run the configured
   checker when present; add one only when adoption is in scope. For checker work, pin
   checker/compiler versions and test relevant generics, arrays, overrides and unannotated
   dependencies because JSpecify support is not identical across tools.

## Rules

- Public constructors and entry points enforce their non-null preconditions before invalid effects,
  preserving the failure contract. Explicit checks can improve blame location; a natural operation
  can suffice when it gives the required failure and ordering. In records explicit checks belong
  in the compact constructor; `List.copyOf` rejects a null list and null elements in the same move.
- Prefer an empty collection when the contract means zero elements. `List.of()` / `Map.of()` /
  `Set.of()` are unmodifiable; preserve a published mutable-return contract with a fresh mutable
  empty collection. Do not collapse unknown/not-loaded/error into empty without an explicit policy.
- `@NullMarked` is metadata, not a runtime guard. Name the actual checker and analyzed scope;
  ordinary `javac` acceptance is not nullness verification. If generated/runtime validation reads
  annotations, verify that path separately rather than crediting the annotation itself.
- `Map.get` returns null for both "absent" and "mapped to null" — resolve it with
  `getOrDefault` when only absence should select a default (an explicitly mapped null remains
  null), or collapse both to absence with `Optional.ofNullable` at the API edge. Only
  `containsKey` distinguishes on a stable nullable map; separate calls race under concurrent
  mutation. `ConcurrentHashMap` forbids null keys/values, making a single `get` unambiguous.
- Prefer empty collections and Optional/result/domain failures where they communicate absence well.
  An explicitly `@Nullable` public return is still a valid Java/JSpecify contract when framework
  conventions, hot-path cost or migration compatibility justify it; callers and overrides must be
  checked consistently. Unannotated ambient null is the defect, not every nullable API.
- Nullness has positions: `String @Nullable []` marks the array reference nullable, while
  `@Nullable String[]` places nullability on its element type; generic element nullness likewise
  differs from container nullness. Use JSpecify type-use syntax accepted by the chosen checker;
  for checker-backed signature changes, add consumer compile tests.
- Override contracts are directional: an implementation must not reject null accepted by its
  supertype, and may return a non-null value where the supertype permits null. When using a checker,
  include both declarations; framework-generated subclasses and unannotated bytecode can hide violations.
- Primitive DTO fields cannot represent “missing” separately from zero/false when a binder applies
  Java defaults. Use boxed/raw DTO fields, required-creator semantics or presence tracking at the
  wire boundary, then convert to primitives after validation.

## NPE diagnosis

1. Read the helpful-NPE expression and full stack, but treat the dereference as the symptom—not
   necessarily the producer.
2. Trace assignments/returns back to the first nullable or unannotated boundary; classify absence,
   invalid input or lifecycle state.
3. Fix the producer contract/conversion and use available checker/caller evidence to find affected
   paths; avoid a local `if (x != null)` that silently drops required work.
4. Add the relevant boundary regression; for checker-backed work, add a compile-time nullness fixture.
   Verify logs/errors do not expose sensitive object contents while diagnosing.

## References

Deliver each null's meaning, affected declaration/boundary, chosen representation and checks
executed. Report any checker version, analyzed scope and unchecked dependencies; pair nullness
compile fixtures with runtime boundary regressions when applicable. Neither annotations nor a
zero-warning partial scan prove that every runtime construction path is safe.

- [Nullability contracts](references/nullability-contracts.md) — read when introducing
  JSpecify to a codebase, deciding annotation placement, or judging whether a flagged
  nullable field is actually a defect.
- [Worked example: hardening a service boundary](references/boundary-hardening.md) — read
  when NPEs originate from deserialised input or repository lookups, or before reviewing
  an inbound adapter.

Attribution

robsonkadesrobsonkades
View sourceMore from robsonkades →
SSkills DirectorySkills Directory

Ship a skill? Prove it's safe.

Free 120-pattern security scan, letter grade, and an embeddable README badge.

Submit a skill

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments (0)

No comments yet. Be the first to comment!

SSkills DirectorySkills Directory

Ship a skill? Prove it's safe.

Free 120-pattern security scan, letter grade, and an embeddable README badge.

Submit a skill

Related Skills

Browser Extension Developer

Use this skill when developing or maintaining browser extension code in the `browser/` directory, including Chrome/Firefox/Edge compatibility, content scripts, background scripts, or i18n updates.

281612 votes

Seo Optimizer

SEO optimization with keyword analysis, readability assessment, technical validation, content quality. Use for search rankings, blog posts, content audits, or encountering keyword density, readability scores, meta tags, schema markup errors.

2132 votes

Google Official Seo Guide

Official Google SEO guide covering search optimization, best practices, Search Console, crawling, indexing, and improving website search visibility based on official Google documentation

1862 votes

Tanstack Start

Build a full-stack TanStack Start app on Cloudflare Workers from scratch — SSR, file-based routing, server functions, D1+Drizzle, better-auth, Tailwind v4+shadcn/ui. Use whenever the user mentions TanStack Start, asks to scaffold a full-stack Cloudflare app with SSR, wants an SSR dashboard, or asks for a React 19 + Cloudflare Workers app with file-based routing and server functions — even if they don't name TanStack Start specifically. No template repo — Claude generates every file fresh per ...

9881 votes

Pentest

PTES-aligned adversarial security audit for backend, frontend, and mobile applications. Produces a CVSS-scored Hacker Report with verified PoCs and phased remediation.

5491 votes
View all in development →