{"slug": "jspecify", "name": "JSpecify", "category": "dev-libs", "category_name": "Libraries and frameworks", "description": "", "recommenders": 3, "commenters": 4, "warners": 0, "score": 3.057, "rising": 1.67, "first": "2026-06-21", "latest": "2026-09-16", "why": "Plus JSpecify annotations get you null denotation that's almost as good as Kotlin's.", "why_is_quote": true, "has_verdict": false, "sentiment": {"recommend": 3, "neutral": 0, "compare": 1, "warn": 0}, "spark": [0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 2, 0], "listed": true, "loved": [], "caveat": "", "short_quote": "Plus JSpecify annotations get you null denotation that's almost as good as Kotlin's.", "kind": "", "icon": true, "domain": "jspecify.dev", "github_repo": null, "official_url": "https://jspecify.dev", "pricing": "", "aliases": ["JSpecify"], "verdict": null, "praise": [{"label": "", "summary": "", "quotes": [{"id": 795548576, "item_id": 49721786, "url": "https://news.ycombinator.com/item?id=49721786", "by": "za3faran", "date": "2026-09-16", "version": null, "stance": "recommend", "quote": "Also solved for Java:", "excerpt": "Also solved for Java: * https://jspecify.dev/docs/user-guide/ * https://openjdk.org/jeps/8303099", "context": "", "use_case": "Null-safety annotations", "switched_from": "", "story": "Java 27"}, {"id": 795420512, "item_id": 49713782, "url": "https://news.ycombinator.com/item?id=49713782", "by": "msgilligan", "date": "2026-09-15", "version": null, "stance": "recommend", "quote": "standardized on JSpecify", "excerpt": "The ecosystem has (at long last) standardized on JSpecify (https://jspecify.dev) for nullability annotations. JSpecify allows you to annotate a package or module with `@NullMarked` and your IDE and build (via ErrorProne+NullAway, typically) will check for null safety. If you develop a library in Java and use it from Kotlin, the built-in Kotlin null-safety will recognize the JSpecify annotations on the library. Null-r", "context": "", "use_case": "Nullability annotations", "switched_from": "", "story": "Java 27"}, {"id": 777961794, "item_id": 48622612, "url": "https://news.ycombinator.com/item?id=48622612", "by": "retrodaredevil", "date": "2026-06-21", "version": null, "stance": "recommend", "quote": "Plus JSpecify annotations get you null denotation that's almost as good as Kotlin's.", "excerpt": "The design of error handling in Go is interesting because they wanted to force people to actually handle errors by returning them as values, but then you as the programmer have to decide whether an error should be returned or a panic should be used. It reminds me of the original intention of checked exceptions in Java: checked exceptions are for things you force the caller to handle, unchecked exceptions are for \"you", "context": "", "use_case": "null annotations in Java", "switched_from": "", "story": "Excessive nil pointer checks in Go"}]}], "caveats": [], "who": [], "tags": [], "use_cases": ["null-safety annotations", "nullability annotations", "null annotations in java"], "compared": [{"slug": "nilaway", "name": "NilAway", "co": 2, "switched_from": 0, "switched_to": 0}], "makers": [], "threads": [{"url": "https://news.ycombinator.com/item?id=49712041", "title": "Java 27", "mentions": 3}, {"url": "https://news.ycombinator.com/item?id=48583407", "title": "Excessive nil pointer checks in Go", "mentions": 1}], "sentiment_by_month": {"2025-11": {}, "2025-12": {}, "2026-01": {}, "2026-02": {}, "2026-03": {}, "2026-04": {}, "2026-05": {}, "2026-06": {"recommend": 1}, "2026-07": {}, "2026-08": {}, "2026-09": {"recommend": 2, "compare": 1}, "2026-10": {}}, "versions": [], "version_unnamed": 0, "family_ref": null, "runs_on": null, "lines": [], "quotes": [{"id": 795548576, "item_id": 49721786, "url": "https://news.ycombinator.com/item?id=49721786", "by": "za3faran", "date": "2026-09-16", "version": null, "stance": "recommend", "quote": "Also solved for Java:", "excerpt": "Also solved for Java: * https://jspecify.dev/docs/user-guide/ * https://openjdk.org/jeps/8303099", "context": "", "use_case": "Null-safety annotations", "switched_from": "", "story": "Java 27"}, {"id": 795490177, "item_id": 49718136, "url": "https://news.ycombinator.com/item?id=49718136", "by": "unscaled", "date": "2026-09-15", "version": null, "stance": "compare", "quote": "Not exactly the same solution as JSpecify, since it doesn't rely on annotations", "excerpt": "Sure it does: https://github.com/uber-go/nilaway Not exactly the same solution as JSpecify, since it doesn't rely on annotations, but it's also more ergonomic. I'm not comparing this to \"null-restricted types\", since that's a draft JEP that hasn't made it even into a preview feature. Go also had multiple proposals for explicit nilability in types, and while they probably have less prospect of ever seeing the light of", "context": "", "use_case": "", "switched_from": "", "story": "Java 27"}, {"id": 795420512, "item_id": 49713782, "url": "https://news.ycombinator.com/item?id=49713782", "by": "msgilligan", "date": "2026-09-15", "version": null, "stance": "recommend", "quote": "standardized on JSpecify", "excerpt": "The ecosystem has (at long last) standardized on JSpecify (https://jspecify.dev) for nullability annotations. JSpecify allows you to annotate a package or module with `@NullMarked` and your IDE and build (via ErrorProne+NullAway, typically) will check for null safety. If you develop a library in Java and use it from Kotlin, the built-in Kotlin null-safety will recognize the JSpecify annotations on the library. Null-r", "context": "", "use_case": "Nullability annotations", "switched_from": "", "story": "Java 27"}, {"id": 777961794, "item_id": 48622612, "url": "https://news.ycombinator.com/item?id=48622612", "by": "retrodaredevil", "date": "2026-06-21", "version": null, "stance": "recommend", "quote": "Plus JSpecify annotations get you null denotation that's almost as good as Kotlin's.", "excerpt": "The design of error handling in Go is interesting because they wanted to force people to actually handle errors by returning them as values, but then you as the programmer have to decide whether an error should be returned or a panic should be used. It reminds me of the original intention of checked exceptions in Java: checked exceptions are for things you force the caller to handle, unchecked exceptions are for \"you", "context": "", "use_case": "null annotations in Java", "switched_from": "", "story": "Excessive nil pointer checks in Go"}]}