---
title: nullの10億ドルの過ちから未来へ Spring Boot 4とJSpecifyが描くnull安全設計
tags:  #wealthnavi #java #jjug  
author: [ウェルスナビ株式会社 技術広報チーム](https://www.docswell.com/user/WN_Tech-PR)
site: [Docswell](https://www.docswell.com/)
thumbnail: https://bcdn.docswell.com/page/5EGR61GXJL.jpg?width=480
description: 2025年11月15日開催のJJUG CCC 2025 Fallで使用した資料です
published: November 15, 25
canonical: https://www.docswell.com/s/WN_Tech-PR/ZM6PPE-2025-11-15-125730
---
# Page. 1

![Page Image](https://bcdn.docswell.com/page/5EGR61GXJL.jpg)

nullの10億ドルの過ちから未来へ
Spring Boot 4とJSpecifyが描くnull安全設計
2025.11.15
尾形 涼介
藤原 将貴
JJUG CCC 2025 FALL


# Page. 2

![Page Image](https://bcdn.docswell.com/page/4JQV4DX57P.jpg)

⾃⼰紹介
尾形 涼介 (Ogata Ryosuke)
ウェルスナビ株式会社
ロボアド開発グループ サービス機能開発チーム
ウェルスナビでは
●
2024年ウェルスナビ株式会社に新卒として⼊社
●
サービスサイト‧APIの開発に従事
やっちまった
ひとこと
●
名前も⾎液型もO型です
2
@2025 WealthNavi Inc.


# Page. 3

![Page Image](https://bcdn.docswell.com/page/K74MQZ6VJ1.jpg)

⾃⼰紹介
藤原 将貴 (Fujiwara Masataka)
ウェルスナビ株式会社
ロボアド開発グループ サービス機能開発チーム
ウェルスナビでは
●
アプリのREST APIの開発
●
最近はフロントの開発もしてます(Thymeleaf)
ひとこと
●
java8からいち早く脱却したい
3
@2025 WealthNavi Inc.


# Page. 4

![Page Image](https://bcdn.docswell.com/page/LJ18PRV4EG.jpg)

アジェンダ
社内で進むSpring Bootアップデートと新たなnull安全性
Javaとnullの歴史：設計思想と進化の軌跡
JSpecifyの概要および使い⽅
NullAwayの概要および使い⽅
導⼊すべきか、⾒送るべきか
© WealthNavi Inc. All Rights Reserved.
4


# Page. 5

![Page Image](https://bcdn.docswell.com/page/GJWZ21LZJ2.jpg)

プロダクト紹介
全⾃動の資産運⽤サービス
ウェルスナビ
「⻑期‧積⽴‧分散」でリターンの最⼤化をめざす
1万円から運⽤できる
全⾃動でおまかせできる
リスクを抑えて運⽤できる
NISAも⾃動で活⽤できる
※画面はイメージです
© WealthNavi Inc. All Rights Reserved.
5


# Page. 6

![Page Image](https://bcdn.docswell.com/page/4EZ1DPML73.jpg)

1
社内で進むSpring Bootアップデートと
新たなnull安全性
© WealthNavi Inc. All Rights Reserved.
6


# Page. 7

![Page Image](https://bcdn.docswell.com/page/Y76L1MNMJV.jpg)

社内で進むSpring Bootアップデート
ロボアドのシステムは、Spring Bootのバージョンが3系以前のものが多くあります。
そのため社内でSpring Bootのアップグレードに関する議論が持ち上がり
3系、4系で導⼊に向けての調査を⾏いました。
7
@2025 WealthNavi Inc.


# Page. 8

![Page Image](https://bcdn.docswell.com/page/G7514Z5QE4.jpg)

JSpecify導⼊により変わるnull安全性
その中で、Spring Boot 4.0.0-M2の公式ブログでは、JSpecify準拠のnull安全アノテーションが
コードベースに導⼊されたことが発表された。
そこで導⼊調査の結果から分かったJSpecifyの仕様と
これまでのnullの歴史を振り返りながら、新たなnull安全性を紹介していく。
https://spring.io/blog/2025/03/10/null-safety-in-spring-apps-with-jspecify-and-null-away
8
@2025 WealthNavi Inc.


# Page. 9

![Page Image](https://bcdn.docswell.com/page/9J21VRNW7R.jpg)

2
1
Javaとnullの歴史：設計思想と進化の軌跡
© WealthNavi Inc. All Rights Reserved.
9


# Page. 10

![Page Image](https://bcdn.docswell.com/page/DEYZ3DP97M.jpg)

アイスブレイク
nullで痛い⽬を⾒たことがある⼈、いますか？
🙋
10
@2025 WealthNavi Inc.


# Page. 11

![Page Image](https://bcdn.docswell.com/page/VJN3V65DJ8.jpg)

冗談ですが、我々は同志です
いたら、裏で⼩⼀時間お話しましょう
11
@2025 WealthNavi Inc.


# Page. 12

![Page Image](https://bcdn.docswell.com/page/YE996LY8E3.jpg)

Javaとnullの歴史年表
トニー‧ホーア⽒がnull参照を
導⼊。後に「10億ドルの過ち」
と発⾔する
1965
nullableアノテーションが乱⽴
（javax, JetBrains, Springなど）
1995
Java 1.0リリース。
nullが標準リテラルとして
登場
2000年代
Kotlinの台頭
「Helpful NullPointerExceptions」が導⼊
2014
2017〜2020 2021~現在
Java 8以降でOptionalが導⼊
12
JSpecifyプロジェクト始動。
null安全の標準化へ
@2025 WealthNavi Inc.


# Page. 13

![Page Image](https://bcdn.docswell.com/page/GE89ZX6Z7D.jpg)

Javaとnullの歴史年表
トニー‧ホーア⽒がnull参照を
導⼊。後に「10億ドルの過ち」
と発⾔する
1965
nullableアノテーションが乱⽴
（javax, JetBrains, Springなど）
1995
Java 1.0リリース。
nullが標準リテラルとして
登場
2000年代
Kotlinの台頭
「Helpful NullPointerExceptions」が導⼊
2014
2017〜2020 2021~現在
Java 8以降でOptionalが導⼊
13
JSpecifyプロジェクト始動。
null安全の標準化へ
@2025 WealthNavi Inc.


# Page. 14

![Page Image](https://bcdn.docswell.com/page/LELWD891JR.jpg)

1965年 トニー‧ホーア⽒がnull参照を導⼊
この時代の⾔語設計では、
変数に「まだ値が設定されていない」ことを⽰す仕組みがなかった
イギリスのコンピュータ科学者 トニー‧ホーア⽒ によってALGOL Wの設計で
参照型に「何も指していない」状態を表すための簡単な⽅法としてnullを導⼊
ALGOL Wとは
教科書や学術論⽂などでアルゴリズム記述のデファクトスタンダード
として30年以上使われた⾔語
14
@2025 WealthNavi Inc.


# Page. 15

![Page Image](https://bcdn.docswell.com/page/4JM9P6Z5EW.jpg)

これが”奴”の到来へ
しかしこの判断が、後に⼤きな問題を引き起こす....
（・∀・）
| | ｶﾞｯ
と
）
| |
Ｙ /ノ
人
/ ）
&lt; &gt;__Λ∩
＿/し&#039; ／／. Ｖ｀Д´）/ ←&gt;&gt;1
（＿フ彡
/
15
@2025 WealthNavi Inc.


# Page. 16

![Page Image](https://bcdn.docswell.com/page/PJRG1P6ZE9.jpg)

奴の名はNullPointerException (ヌルポ)、それが10億ドルの過ちへ
nullが世界中で、NullPointerException (ヌルポ)として膨⼤なバグやクラッ
シュを引き起こす
後にトニー・ホーア⽒は
「私は誘惑に負けてnull参照を導⼊した。それは私の10億ドルの過ちだった」
と発⾔
https://qconlondon.com/london-2009/qconlondon.com/london-2009/presentation/Null%2bReferences_%2bThe%2bBillion%2bDollar%2bMistake.html
16
@2025 WealthNavi Inc.


# Page. 17

![Page Image](https://bcdn.docswell.com/page/PEXXY3M1EX.jpg)

Javaとnullの歴史年表
トニー‧ホーア⽒がnull参照を
導⼊。後に「10億ドルの過ち」
と発⾔する
1965
nullableアノテーションが乱⽴
（javax, JetBrains, Springなど）
1995
Java 1.0リリース。
nullが標準リテラルとして
登場
2000年代
Kotlinの台頭
「Helpful NullPointerExceptions」が導⼊
2014
2017〜2020 2021~現在
Java 8以降でOptionalが導⼊
17
JSpecifyプロジェクト始動。
null安全の標準化へ
@2025 WealthNavi Inc.


# Page. 18

![Page Image](https://bcdn.docswell.com/page/3EKW3YGMED.jpg)

1995年 Javaが世界に登場。だが、“null”という影も連れてきた…
1995年にJava 1.0 がリリースで、この時点からnull が導⼊される
「何も参照していない状態」を表す特別な値として利⽤される
特徴
●
全ての参照型には必ずnullが代⼊可能な設計
●
プリミティブ型には null を代⼊できない
●
null を参照するとヌルポ が発⽣
18
@2025 WealthNavi Inc.


# Page. 19

![Page Image](https://bcdn.docswell.com/page/L731G9N2J5.jpg)

Javaにおけるnullの課題① 型システムでnullを区別できない
●
●
●
Javaでは、すべての参照型にnullが代⼊可能という⾔語仕様になっている
このため、型レベルで「nullableかどうか」を表現できない
結果として、静的解析ではnullの有無を判定できない
String name = getName(); // 外部依存
if (flag) {
name = null; // 条件分岐でnullになる可能性
}
System.out.println(name.length()); // 実行時にヌルポの可能性
静的解析は通るが、実⾏時にエラーが起きる
19
@2025 WealthNavi Inc.


# Page. 20

![Page Image](https://bcdn.docswell.com/page/87DX1GW6EG.jpg)

Javaにおけるnullの課題② Javaのnull設計における曖昧さ
●
●
nullを許容するかどうかが明⽰されないため、設計書やコードコメントで補⾜する必要
がある
チーム内で「この引数はnullを渡していいのか？」「戻り値がnullになる可能性はある
か？」という議論が発⽣
public String getDisplayName(User user) {
if (user == null || user.getName() == null) {
return &quot;Unknown&quot;;
}
return user.getName();
}
防御的コードが⼤量に必要になることで、可読性や保守性が低下
20
@2025 WealthNavi Inc.


# Page. 21

![Page Image](https://bcdn.docswell.com/page/VJPPQ3XZJ8.jpg)

Javaとnullの歴史年表
トニー‧ホーア⽒がnull参照を
導⼊。後に「10億ドルの過ち」
と発⾔する
1965
nullableアノテーションが乱⽴
（javax, JetBrains, Springなど）
1995
Java 1.0リリース。
nullが標準リテラルとして
登場
2000年代
Kotlinの台頭
「Helpful NullPointerExceptions」が導⼊
2014
2017〜2020 2021~現在
Java 8以降でOptionalが導⼊
21
JSpecifyプロジェクト始動。
null安全の標準化へ
@2025 WealthNavi Inc.


# Page. 22

![Page Image](https://bcdn.docswell.com/page/2EV254LMEQ.jpg)

2000年代 null安全アノテーションの乱⽴
FindBugsやIntelliJ IDEAなどで静的解析をするため
それぞれ独⾃の@Nullableや@Nonnullアノテーションを定義
それらは、⾃分たちの解析に最適なアノテーションを作った
互換性がなくライブラリ間で混乱を招いていた
[stackoverﬂowから翻訳して引⽤]
JSR 305 または Jetbrains の IntelliJ 向け独⾃アノテーションで実現可能になったコー
ド検査機能は本当に気に⼊っています。残念ながら、両実装（JSR 305 と Jetbrains
のもの）は互いにうまく混在しません
https://stackoverflow.com/questions/4468599/nullable-notnull-with-intellij-idea-maven-jsr-305
22
@2025 WealthNavi Inc.


# Page. 23

![Page Image](https://bcdn.docswell.com/page/57GR61XXEL.jpg)

null安全アノテーション表
Null関連アノテーション
定義元
主な利用シーン
@Nullable, @NotNull
JetBrains
IntelliJ IDEAでの補完・警告
@Nullable
Spring Framework
Spring内部で使用
@Nullable, @NonNull
FindBugs / SpotBugs
静的解析ツール向け。FindBugs系で使われる
@Nullable, @NonNull
Checker Framework
高度な型チェックが可能。学術寄り
@NonNull
Lombok
コンストラクタやメソッド引数のnullチェックを自動
生成
23
@2025 WealthNavi Inc.


# Page. 24

![Page Image](https://bcdn.docswell.com/page/4EQV4D85JP.jpg)

乱⽴により開発現場での混乱
●
同じ名前でも別物
○ Spring FrameworkとJetBrainsの@Nullable、同じ名前だが別物
●
IDEで警告が出ない、補完されない
○ JetBrains系アノテーションはIntelliJで補完。しかしSpring Framework系は補完
されない
○ @Nullableを付けても、IDEがnullチェックをしてくれない → 意味がない
●
チーム内で「どのアノテーションを使うべきか？」という議論が発⽣
○ さらに、プロジェクトごとに使われているアノテーションが違うと統⼀が困難に
null安全性の向上を目指したはずが、逆に混乱を招いた
24
@2025 WealthNavi Inc.


# Page. 25

![Page Image](https://bcdn.docswell.com/page/KJ4MQZ2VE1.jpg)

JSR-305がJava標準のnull安全アノテーション導⼊へ
そこで2006年にGoogleが提案したJSR-305が動き出す
IDEや静的解析ツール（IntelliJ, SpotBugsなど）が、統⼀されたアノテーションを
使ってnullの有無を正確に解析できるようになること
ついにJavaは新たなnull安全の時代へ
25
@2025 WealthNavi Inc.


# Page. 26

![Page Image](https://bcdn.docswell.com/page/LE18PRM47G.jpg)

とはならず....
休止
26
@2025 WealthNavi Inc.


# Page. 27

![Page Image](https://bcdn.docswell.com/page/GEWZ213ZE2.jpg)

JSR-305は採⽤されず、null安全アノテーションの乱⽴のまま...
JSR-305はコミュニティ内で議論が停滞し、休⽌してしまった
結局正式なJava標準として採⽤されなかった
null安全アノテーションは、乱⽴したままになってしまう
27
@2025 WealthNavi Inc.


# Page. 28

![Page Image](https://bcdn.docswell.com/page/47Z1DPVLJ3.jpg)

Javaとnullの歴史年表
トニー‧ホーア⽒がnull参照を
導⼊。後に「10億ドルの過ち」
と発⾔する
1965
nullableアノテーションが乱⽴
（javax, JetBrains, Springなど）
1995
Java 1.0リリース。
nullが標準リテラルとして
登場
2000年代
Kotlinの台頭
「Helpful NullPointerExceptions」が導⼊
2014
2017〜2020 2021~現在
Java 8以降でOptionalが導⼊
28
JSpecifyプロジェクト始動。
null安全の標準化へ
@2025 WealthNavi Inc.


# Page. 29

![Page Image](https://bcdn.docswell.com/page/YJ6L1M5MEV.jpg)

2014年 Java 8でOptional導⼊
JSR-305のようなアノテーションベースのnull安全がうまくいかなかった
Java 8で⾔語レベルでnullを扱う新しい⽅法として
Optional が導⼊
29
@2025 WealthNavi Inc.


# Page. 30

![Page Image](https://bcdn.docswell.com/page/GJ514ZYQ74.jpg)

Optionalとは何か？
●
●
●
Java 8で導⼊されたnull安全のための型
nullの有無を型で表現することで、明⽰的な設計が可能に
Optionalは「値があるかもしれない」を型で⽰す
Optional&lt;String&gt; getName(); // nullの可能性を型で表現
30
@2025 WealthNavi Inc.


# Page. 31

![Page Image](https://bcdn.docswell.com/page/9E21VRGWJR.jpg)

Optionalのメリット
●
メリット
○
コードの意図が明確になる：nullになる可能性を型で表現
○
ヌルポのリスクが低減する：値の存在確認が強制される
○
メソッドチェーンによる簡潔な記述が可能：複雑な条件分岐を減らせる
Optional.ofNullable(name)
.map(String::length)
.orElse(0);
31
@2025 WealthNavi Inc.


# Page. 32

![Page Image](https://bcdn.docswell.com/page/D7YZ3DV9JM.jpg)

Optionalの限界と注意点① Optional ⾃体が null になり得る
Optionalはラッパーであるため、
Optionalインスタンス⾃体にnullを代⼊することが可能
Optional&lt;User&gt; userOpt = null; // コンパイルエラーにはならない
Optionalで包んだからといってnullの危険性が完全に排除されるわけではない
Javaの型システムはOptionalを「null安全な型」として扱っていない
32
@2025 WealthNavi Inc.


# Page. 33

![Page Image](https://bcdn.docswell.com/page/VEN3V6MDE8.jpg)

Optionalの限界と注意点② パフォーマンス‧互換性
Optionalのパフォーマンスオーバーヘッド
●
●
●
Optionalはラッパーなので、値を扱うたびにオブジェクトを⽣成
短命なOptionalを⼤量⽣成 → GC（ガベージコレクション）負荷が増える
設計上は「戻り値だけ」に限定して使うのが安全
Kotlinや型安全機構との⾮互換
●
●
Kotlinのnull安全型（String?）とは別概念
JavaのOptionalはラッパーでしかなく、Kotlinの型推論に反映されない
33
@2025 WealthNavi Inc.


# Page. 34

![Page Image](https://bcdn.docswell.com/page/Y7996LN873.jpg)

Javaとnullの歴史年表
トニー‧ホーア⽒がnull参照を
導⼊。後に「10億ドルの過ち」
と発⾔する
1965
nullableアノテーションが乱⽴
（javax, JetBrains, Springなど）
1995
Java 1.0リリース。
nullが標準リテラルとして
登場
2000年代
Kotlinの台頭
「Helpful NullPointerExceptions」が導⼊
2014
2017〜2020 2021~現在
Java 8以降でOptionalが導⼊
34
JSpecifyプロジェクト始動。
null安全の標準化へ
@2025 WealthNavi Inc.


# Page. 35

![Page Image](https://bcdn.docswell.com/page/G789ZXKZJD.jpg)

2019年 Kotlinの台頭
この時期からKotlinが⾔語仕様でnull安全が担保されている⾔語として台頭
特徴
●
●
●
JetBrainsによって開発された静的型付けのプログラミング⾔語
Javaとの⾼い互換性を持ち、⾔語仕様でnull安全が担保されている
Androidアプリ開発とバックエンド開発の両⽅で⽤いられる
35
@2025 WealthNavi Inc.


# Page. 36

![Page Image](https://bcdn.docswell.com/page/L7LWD8Z1ER.jpg)

Kotlin台頭の流れ
● 2011年：開発開始
● 2016年：Kotlin 1.0正式リリース
● 2017年：GoogleがKotlinをAndroid開発の公式⾔語として採⽤
● 2018年〜2020年：Spring FrameworkがKotlinをサポート
● 2020年~現在：バックエンドでも企業採⽤が加速
36
@2025 WealthNavi Inc.


# Page. 37

![Page Image](https://bcdn.docswell.com/page/4EM9P6V57W.jpg)

Kotlinのnull安全性① 型システムでnull許容を明⽰
型
説明
String
nullを許容しない型（non-null型）
→ null を代⼊するとコンパイルエラー
String?
nullを許容する型（nullable型）
→ null を代⼊可能
val nickname: String = null // ❌ 代入不可
val nickname: String? = null // OK 代入可能
nullが代⼊される可能性を型で表現することで、設計段階から安全性を確保
37
@2025 WealthNavi Inc.


# Page. 38

![Page Image](https://bcdn.docswell.com/page/PERG1P2Z79.jpg)

Kotlinのnull安全性② コンパイル時にnull安全を保証
Kotlinでは、nullable型に対して安全でないアクセスをすると静的解析でエラー
Javaとの⼤きな違いであり、Kotlinのnull安全性の⼀番の要因
var name: String? = getName()
if (ﬂag) {
name = null
}
println(name.length) // ❌ コンパイルエラー
Javaでは実⾏時にエラーになるが、Kotlinでは事前に防げる
38
@2025 WealthNavi Inc.


# Page. 39

![Page Image](https://bcdn.docswell.com/page/P7XXY3D17X.jpg)

Kotlinのnull安全性③ null安全オペレーターで安全にアクセス
nullable型(例:String?)の変数にそのままアクセスすると、 ヌルポのリスク
安全にアクセスするための構⽂が、null安全オペレーター
オペレーター
役割
使⽤例
説明
?.（安全呼び出し）
nullでなければアクセス
user?.name
userがnullならnullを返す
?:（エルビス演算⼦）
null時のデフォルト値
user?.name ?: &quot;ゲスト&quot;
user?.nameがnullなら &quot;ゲスト&quot; を返す
!!（⾮nullアサーション）
nullでないと断⾔
user!!.name
userがnullなら例外発⽣（⾮推奨）
39
@2025 WealthNavi Inc.


# Page. 40

![Page Image](https://bcdn.docswell.com/page/37KW3YXM7D.jpg)

Kotlinにおけるnull安全設計
「nullableかどうかは型で明示。迷いなし」
「nullチェックはコンパイラが自動で指摘」
「null安全オペレーターで、nullでも落ち着いて処理」
「Optional？不要。言語がすでにnull安全」
40
@2025 WealthNavi Inc.


# Page. 41

![Page Image](https://bcdn.docswell.com/page/LJ31G952E5.jpg)

Javaにおけるnull安全設計
「nullが来るかもしれない？とりあえずif (obj != null)で囲め！ 囲め！」
「例外？ そんなもんtry-catchで受け⽌めろ！」
「Optional？ 使い⽅は... まぁ、なんとかなんだろ！」
「アノテーション？プロジェクトごとにバラバラだけど、気合で統⼀感出せ！」
「レビューで『nullチェック漏れてるよ』って⾔われたら、⼼で泣いてコードで耐える！」
Kotlinは後発⾔語としてnull安全を型システムに組み込めた
Javaは互換性やエコシステムの広さを重視して進化してきた役割の違いが、この設計に影響した
41
@2025 WealthNavi Inc.


# Page. 42

![Page Image](https://bcdn.docswell.com/page/8JDX1GD67G.jpg)

JavaとKotlinのnull設計思想の対⽐
観点
Java
Kotlin
null許容性
型に含まれない
型で明⽰される
nullチェック
⼿動で書く
コンパイルで強制される
安全性
実⾏時にヌルポが起きる
コンパイル時に防げる
設計の明⽰性
弱い（Javadoc頼り）
強い（型で表現）
42
@2025 WealthNavi Inc.


# Page. 43

![Page Image](https://bcdn.docswell.com/page/VEPPQ36ZE8.jpg)

2020年 Java 14でヌルポメッセージ改善
Java 14では、JEP 358として提案された「Helpful NullPointerExceptions」が導⼊
ヌルポ発⽣時のエラーメッセージが、分かりやすくなったという改善です
[OpenJDK公式から翻訳して引⽤]
どの変数が null であったかを正確に記述することにより、JVM によって⽣成され
た NullPointerExceptions の使いやすさを向上します
https://openjdk.org/jeps/358
43
@2025 WealthNavi Inc.


# Page. 44

![Page Image](https://bcdn.docswell.com/page/27V2543M7Q.jpg)

従来のNullPointerExceptionのスタックトレース
Java 13以前
String name = null;
System.out.println(name.length());
Exception in thread &quot;main&quot; java.lang.NullPointerException
スタックトレースだけだと具体的に何がnullなのかわからない
44
@2025 WealthNavi Inc.


# Page. 45

![Page Image](https://bcdn.docswell.com/page/5JGR613X7L.jpg)

Helpful NullPointerExceptions導⼊後
Java 14以降
以下のオプションを指定することで有効になる
-XX:+ShowCodeDetailsInExceptionMessages
String name = null;
System.out.println(name.length());
Exception in thread &quot;main&quot; java.lang.NullPointerException: Cannot invoke
&quot;String.length()&quot; because &quot;name&quot; is null
nullだった具体的な式や変数名が表⽰されるため、デバッグ効率が⼤幅に向上
45
@2025 WealthNavi Inc.


# Page. 46

![Page Image](https://bcdn.docswell.com/page/47QV4D55EP.jpg)

Javaとnullの歴史年表
トニー‧ホーア⽒がnull参照を
導⼊。後に「10億ドルの過ち」
と発⾔する
1965
nullableアノテーションが乱⽴
（javax, JetBrains, Springなど）
1995
Java 1.0リリース。
nullが標準リテラルとして
登場
2000年代
Kotlinの台頭
「Helpful NullPointerExceptions」が導⼊
2014
2017〜2020 2021~現在
Java 8以降でOptionalが導⼊
46
JSpecifyプロジェクト始動。
null安全の標準化へ
@2025 WealthNavi Inc.


# Page. 47

![Page Image](https://bcdn.docswell.com/page/KE4MQZ9V71.jpg)

2021年〜現在 JSpecifyプロジェクト始動
トニー‧ホーア⽒によるnullの導⼊から始まり、JSR-305の停滞、アノテーションの乱⽴など
⾔語仕様としてのnull安全性には⼀貫性を⽋いていた
こうした背景から本格的なnull安全の標準化に向けて動き出す
それが、Googleを中⼼に始動した JSpecifyプロジェクト
47
@2025 WealthNavi Inc.


# Page. 48

![Page Image](https://bcdn.docswell.com/page/L718PRK4JG.jpg)

3
1
JSpecifyの概要と使い⽅
© WealthNavi Inc. All Rights Reserved. 48


# Page. 49

![Page Image](https://bcdn.docswell.com/page/G7WZ21DZ72.jpg)

JSpecifyとは
null関連アノテーションのライブラリ
Google社が⽴ち上げたプロジェクト
JSpecifyはこれまで乱雑していたnullに関係するライブラリや静的解析ツールなどのプロ
ジェクトと合意形成を取ることでnull関連のアノテーションを統⼀することを⽬標
として掲げている
Spring Boot4.0.0で採⽤
Spring Boot3系時点では
Spring独⾃のアノテーション(@NonNull,@Nullableなど)を⽤いているが
Spring Boot 4.0.0では、JSpecifyを代わりに使うようになっている
49
@2025 WealthNavi Inc.


# Page. 50

![Page Image](https://bcdn.docswell.com/page/4JZ1DPGLE3.jpg)

JSpecifyプロジェクトを⽀える組織
組織
プロジェクト
Broadcom
Spring
Google
Android, Error Prone, Guava
JetBrains
Kotlin, Intellij IDEA
Meta
Infer
MicroSoft
Azure SDK for Java
Oracle
OpenJDK
PMD Team
PMD
Sonar
SonarQube, SonarCloud, SonarLint
Uber
NullAway
EISOP Team
EISOP
50
@2025 WealthNavi Inc.


# Page. 51

![Page Image](https://bcdn.docswell.com/page/YE6L1MYM7V.jpg)

JSpecify導⼊のメリット‧デメリット
メリット
● ヌルポ発⽣率を極限まで減らす
● null安全チェックの静的解析が簡単にできる(NullAway)
● Kotlinとのシームレスな連携（相互運⽤性）
○
KotlinからJavaコードを呼び出す時に、戻り値がnull許容/⾮許容か解析
○
JavaからKotlinへの変換時、@Nullableが付いた型はnull許容型(?)へ変換される
デメリット
● 学習コストおよび「習慣化」の壁
51
@2025 WealthNavi Inc.


# Page. 52

![Page Image](https://bcdn.docswell.com/page/GE514ZGQJ4.jpg)

JSpecify：類似ライブラリとの違い
JSpecifyの@Nullable
jakarta.annotationの@Nullable
52
@2025 WealthNavi Inc.


# Page. 53

![Page Image](https://bcdn.docswell.com/page/9721VRYWER.jpg)

JSpecify：類似ライブラリとの違い
@Target(TYPE_USE)によって型が使われてる箇所なら、基本的にどこでも使えるようになった
例えばジェネリクス、インナークラス、配列⾃⾝(変数の型)へのアノテーション付与は
jakarta.annotationではエラーになるが、JSpecifyでは問題なく使えるようになっている
JSpecifyの@Nullableではエラーに
ならない
jakarta.annotationの@Nullableではエラー
53
@2025 WealthNavi Inc.


# Page. 54

![Page Image](https://bcdn.docswell.com/page/DJYZ3DG9EM.jpg)

JSpecify：導⼊⽅法
Gradle
dependencies {
api(&quot;org.jspecify:jspecify:1.0.0&quot;)
}
※ Spring Boot 4.0.0ではデフォルトで⼊っているので、依存関係書かなくてもOK！
Java互換性
Java8以上が必要
54
@2025 WealthNavi Inc.


# Page. 55

![Page Image](https://bcdn.docswell.com/page/V7N3V6GD78.jpg)

アノテーション解説
© WealthNavi Inc. All Rights Reserved. 55


# Page. 56

![Page Image](https://bcdn.docswell.com/page/YJ996LW8J3.jpg)

アノテーション解説：@Nullable
型がnull許容であることを⽰す時に使う
使⽤できる箇所はフィールド、戻り値、引数、ジェネリクスなど。クラス⾃体には使⽤できない
56
@2025 WealthNavi Inc.


# Page. 57

![Page Image](https://bcdn.docswell.com/page/GJ89ZXNZED.jpg)

アノテーション解説：@NonNull
型がnull⾮許容であることを⽰す時に使う
使⽤できる箇所はフィールド、戻り値、引数、ジェネリクスなど。クラス⾃体には使⽤できない
基本的に使わない
なぜなら‧‧‧次のスライドで話す@NullMarkedで@NonNullを網羅できるため
57
@2025 WealthNavi Inc.


# Page. 58

![Page Image](https://bcdn.docswell.com/page/LJLWD8P17R.jpg)

アノテーション解説：@NullMarked
nullが出ない箇所に⼀々、@NonNullをつけるのは⾯倒
そこで活躍するのが@NullMarked
@NullMarkedをpackage-info.javaに付けるとパッケージ内のクラスを⼀括で nonNull 扱いにできる
ただし、@Nullableが付与されている箇所は上書きされず、サブパッケージには適⽤されない
58
@2025 WealthNavi Inc.


# Page. 59

![Page Image](https://bcdn.docswell.com/page/47M9P645JW.jpg)



# Page. 60

![Page Image](https://bcdn.docswell.com/page/P7RG1PWZJ9.jpg)

アノテーション解説：@NullUnmarked
ロジックを持たないクラス(エンティティやモデルなど)によってはnull安全チェックの対象にしたくな
い
そこで活躍するのが@NullUnmarked
@NullUnmarkedが付与されたメソッド、クラス、パッケージではnull安全チェックの対象外となる
メソッドに宣言
パッケージに宣言
(package-info.java)
クラスに宣言
60
@2025 WealthNavi Inc.


# Page. 61

![Page Image](https://bcdn.docswell.com/page/PJXXY3P1JX.jpg)

アノテーション解説：@NullUnmarked
メソッドに宣⾔
61
@2025 WealthNavi Inc.


# Page. 62

![Page Image](https://bcdn.docswell.com/page/3JKW3YDMJD.jpg)

アノテーション解説：@NullUnmarked
メソッドに宣⾔
クラスに宣⾔
62
@2025 WealthNavi Inc.


# Page. 63

![Page Image](https://bcdn.docswell.com/page/LE31G9R275.jpg)

アノテーション解説：@NullUnmarked
パッケージに宣言 (package-info.java)
63
@2025 WealthNavi Inc.


# Page. 64

![Page Image](https://bcdn.docswell.com/page/8EDX1GY6JG.jpg)

Tips
© WealthNavi Inc. All Rights Reserved. 64


# Page. 65

![Page Image](https://bcdn.docswell.com/page/V7PPQ32Z78.jpg)

JSpecifyのTips：IntelliJ IDEAのリアルタイムコード解析
IntelliJ IDEAを使うと静的解析をしなくても、リアルタイムでJSpecifyの警告を出してくれる
しかし、2025年11⽉時点ではNullAwayによる静的解析結果と異なる警告もあるので注意が必要
(おそらくNullAwayの解析結果の⽅が正しい)
65
@2025 WealthNavi Inc.


# Page. 66

![Page Image](https://bcdn.docswell.com/page/2JV254DMJQ.jpg)

JSpecifyのTips：プリミティブ型には使えない
プリミティブ型にはnullを代⼊できないため、アノテーションを付与することもできない
66
@2025 WealthNavi Inc.


# Page. 67

![Page Image](https://bcdn.docswell.com/page/5EGR61YXJL.jpg)

JSpecifyのTips：配列型での使い⽅
配列の要素に対してnullableを適⽤したい場合はString[]の前に@Nullableをつける
@Nullable String[] example
配列⾃⾝にnullableを適⽤したい場合はStringと[]の間に@Nullableをつける
String @Nullable [] example
67
@2025 WealthNavi Inc.


# Page. 68

![Page Image](https://bcdn.docswell.com/page/4JQV4DM57P.jpg)

JSpecifyのTips：FQCNで記載された型での使い⽅
❌
public @Nullable com.wealthnavi.SampleClass method() {...
パッケージ名と型名の間に付けるのが正しい
⭕
public com.wealthnavi.@Nullable SampleClass method() {...
68
@2025 WealthNavi Inc.


# Page. 69

![Page Image](https://bcdn.docswell.com/page/K74MQZVVJ1.jpg)

実践編クイズ
© WealthNavi Inc. All Rights Reserved. 69


# Page. 70

![Page Image](https://bcdn.docswell.com/page/LJ18PR34EG.jpg)

クイズの「前提ルール」
JSpecifyのNonNullがデフォルトと⾔う考え⽅に慣れてもらうために、
パッケージ全体に @NullMarked が適⽤されていることをクイズの前提とします
private String func(List&lt;String&gt; list) {
return list.getFirst();
}
@NullMarkedの下では、暗黙的に@NonNull
が適⽤される
private @NonNull String func(@NonNull List&lt;@NonNull String&gt; list) {
return list.getFirst();
}
70
@2025 WealthNavi Inc.


# Page. 71

![Page Image](https://bcdn.docswell.com/page/GJWZ21PZJ2.jpg)

JSpecifyのTips：オーバライドメソッドにおける使い⽅①
public class SuperClass {
public String method() {...
public class SubClass extends SuperClass {
@Override
public @Nullable String method() {...
71
@2025 WealthNavi Inc.


# Page. 72

![Page Image](https://bcdn.docswell.com/page/4EZ1DPKL73.jpg)

JSpecifyのTips：オーバライドメソッドにおける使い⽅①
public class SuperClass {
public String method() {...
public class SubClass extends SuperClass {
@Override
public @Nullable String method() {...
スーパークラスのメソッドの戻り値が@NonNullの時、サブクラスのオーバーライドメ
ソッドの戻り値には@Nullableをつけることはできない
理由
スーパークラスのメソッドにはnullが返ってこないと契約しているのに対し、
サブクラスではnullを返してしまい、契約違反となる(リスコフの置換原則)
72
@2025 WealthNavi Inc.


# Page. 73

![Page Image](https://bcdn.docswell.com/page/Y76L1MQMJV.jpg)

JSpecifyのTips：オーバライドメソッドにおける使い⽅①
public class SuperClass {
public @Nullable String method() {...
public class SubClass extends SuperClass {
@Override
public @Nullable String method() {...
public class SubClass extends SuperClass {
@Override
public String method() {....
どっちでも
OK
サブクラスのオーバーライドメソッドの戻り値に@Nullableを付けたい場合、スーパー
クラスのメソッドの戻り値に@Nullableを付ける必要がある
73
@2025 WealthNavi Inc.


# Page. 74

![Page Image](https://bcdn.docswell.com/page/G7514ZRQE4.jpg)

JSpecifyのTips：オーバライドメソッドにおける使い⽅②
public class SuperClass {
public String method(@Nullable Object obj) {...
public class SubClass extends SuperClass {
@Override
public String method(Object obj) {...
74
@2025 WealthNavi Inc.


# Page. 75

![Page Image](https://bcdn.docswell.com/page/9J21VRDW7R.jpg)

JSpecifyのTips：オーバライドメソッドにおける使い⽅②
public class SuperClass {
public String method(@Nullable Object obj) {...
public class SubClass extends SuperClass {
@Override
public String method(@Nullable Object obj) {...
スーパークラスのメソッドの引数がNullableの時、サブクラスのオーバーライドメソッ
ドの引数にも@Nullableをつけないといけない
理由
スーパークラスのメソッド引数にはnullを許容すると契約しているのに対し、
サブクラスではnullを許容しないため、契約違反となる
75
@2025 WealthNavi Inc.


# Page. 76

![Page Image](https://bcdn.docswell.com/page/DEYZ3D297M.jpg)

JSpecifyのTips：オーバライドメソッドにおける使い⽅②
public class SuperClass {
public String method(Object obj) {...
public class SubClass extends SuperClass {
@Override
public String method(@Nullable Object obj) {...
public class SubClass extends SuperClass {
@Override
public String method(Object obj) {...
どっちでも
OK
スーパクラスのメソッドの引数がNonNullなら、
サブクラスでのメソッドの引数はNullableでもNonNullでも良い
76
@2025 WealthNavi Inc.


# Page. 77

![Page Image](https://bcdn.docswell.com/page/VJN3V68DJ8.jpg)

JSpecifyのTips：ジェネリクス型での使い⽅
以下のクラスを使うケースを考えてみてください
使い⽅が正しいケース
public class NumberList&lt;E extends Number&gt; implements List&lt;E&gt;
NumberList&lt;Integer&gt; numberList = new NumberList&lt;&gt;();
{...}
77
@2025 WealthNavi Inc.


# Page. 78

![Page Image](https://bcdn.docswell.com/page/YE996LK8E3.jpg)

JSpecifyのTips：ジェネリクス型での使い⽅
A
NumberList&lt;@Nullable Integer&gt; numberList = new NumberList&lt;&gt;();
B
NumberList&lt;Integer&gt; numberList = new NumberList&lt;&gt;();
78
@2025 WealthNavi Inc.


# Page. 79

![Page Image](https://bcdn.docswell.com/page/GE89ZXRZ7D.jpg)

JSpecifyのTips：ジェネリクス型での使い⽅
B
NumberList&lt;Integer&gt; numberList = new NumberList&lt;&gt;();
79
@2025 WealthNavi Inc.


# Page. 80

![Page Image](https://bcdn.docswell.com/page/LELWD8K1JR.jpg)

JSpecifyのTips：ジェネリクス型での使い⽅
正解はB
NumberList&lt;Integer&gt; numberList = new NumberList&lt;&gt;();
Aは間違い
NumberList&lt;@Nullable Integer&gt; numberList = new NumberList&lt;&gt;();
解説
型となっているNumberListのジェネリクス、E extends Numberは@NullMarkedが
付与されているため、@NonNull E extends Numberとみなされる
よって、NumberListをインスタンス化する時は、ジェネリクスに@Nullableを付与
することができない
80
@2025 WealthNavi Inc.


# Page. 81

![Page Image](https://bcdn.docswell.com/page/4JM9P625EW.jpg)

1
4
NullAwayの概要および使い⽅
© WealthNavi Inc. All Rights Reserved. 81


# Page. 82

![Page Image](https://bcdn.docswell.com/page/PJRG1PMZE9.jpg)

NullAwayとは
null安全チェック⽤の静的解析ツール
Uber社のOSS
Google社のErrorProne(静的解析ツール)のプラグインとして動く
他ツールとの優位性
ビルド時オーバーヘッドの⽐較
●
●
類似の静的解析ツール
○ 2.8倍 〜 5.1倍
NullAway
○ 1.15倍
(※ 2019年の論⽂ NullAway: Practical Type-Based Null Safety for Javaより https://arxiv.org/abs/1907.02127)
82
@2025 WealthNavi Inc.


# Page. 83

![Page Image](https://bcdn.docswell.com/page/PEXXY3V1EX.jpg)

NullAway：導⼊⽅法(Gradle)
plugins {
id(&quot;net.ltgt.errorprone&quot;) version &quot;4.3.0&quot;
}
dependencies {
errorprone &quot;com.uber.nullaway:nullaway:0.12.10&quot;
errorprone &quot;com.google.errorprone:error_prone_core:2.42.0&quot;
}
import net.ltgt.Gradle.errorprone.CheckSeverity
tasks.withType(JavaCompile).configureEach {
options.errorprone {
// ErrorProneの警告を無効化
disableAllChecks = true
// NullAwayの指摘をエラーとして扱う
check(&quot;NullAway&quot;, CheckSeverity.ERROR)
// null安全チェックしたいパッケージを指定
option(&quot;NullAway:AnnotatedPackages&quot;, &quot;com.sample&quot;)
}
}
83
@2025 WealthNavi Inc.


# Page. 84

![Page Image](https://bcdn.docswell.com/page/3EKW3YQMED.jpg)

84


# Page. 85

![Page Image](https://bcdn.docswell.com/page/L731G9P2J5.jpg)

5
1
導⼊すべきか、⾒送るべきか
© WealthNavi Inc. All Rights Reserved. 85


# Page. 86

![Page Image](https://bcdn.docswell.com/page/87DX1GL6EG.jpg)

導⼊すべきか、⾒送るべきか
JSpecify&amp;NullAway導⼊をすべきケース
● Spring Bootを使っていて今後数年内でSpringバージョンアップを計画しているケース
● これから新規でプロジェクトを⽴ち上げるケース
● JavaとKotlinが混在しているケース
● Kotlinへの移⾏をしようか悩んでいるケース
導⼊を⾒送ってもいいケース
● Gradle, Maven, Bazel以外のビルドツールを使⽤しているケース
● Java8以下を使っているケース(ErrorProneの互換性影響)
86
@2025 WealthNavi Inc.


# Page. 87

![Page Image](https://bcdn.docswell.com/page/VJPPQ34ZJ8.jpg)

We are hiring
採⽤強化中
安⼼して使える⾦融インフラを共につくる仲間募集
https://recruit.wealthnavi.com/
© WealthNavi Inc. All Rights Reserved.
87


# Page. 88

![Page Image](https://bcdn.docswell.com/page/2EV254XMEQ.jpg)

重要な注意事項
● 本資料は、断定的判断を提供するものではなく、情報を提供することのみを⽬的としており、いかなる種類の商
品も勧誘するものではありません。最終的な決定は、お客様⾃⾝で判断するものとし、当社はこれに⼀切関与せ
ず、また、⼀切の責任を負いません。
● 本資料には将来の出来事に関する予想が含まれている場合がありますが、それらは予想であり、また、本資料の
内容の正確性、信頼性、完全性、適時性等を⼀切保証するものではありません。本資料に基づいて被ったいかな
る損害についても、当社は⼀切の責任を負いません。また、当社は、新しい情報や将来の出来事その他の情報に
ついて、更新⼜は訂正する義務を負いません。
● 本資料を利⽤することによりお客様に⽣じた直接的損害、間接的損害、派⽣的損害その他いかなる損害について
も、当社は⼀切の責任を負いません。
商号等：ウェルスナビ株式会社
金融商品取引業者 関東財務局長（金商）
第2884号 加入協会：日本証券業協会 一般社団法人日本投資顧問業協会
© WealthNavi Inc. All Rights Reserved.


