null・undefined・None:「ない」を表す値の扱いは言語ごとに何が違うのか
「値が無いかもしれない」という状態を、言語ごとにどう表現し、どう検出するかは大きく異なります。エラーメッセージだけを覚えても他言語では通用しないため、7言語の実際の出力を並べます。
言語ごとの現れ方
Java: NullPointerException の原因と直し方
1 public class Main { 2 public static void main(String[] args) { 3 String s = null; ^ 4 System.out.println(s.length()); 5 } 6 }
nullに対するメソッド呼び出しはNullPointerExceptionという専用の例外になります。スタックトレースで発生箇所まで特定できます。
Python: Noneに対してメソッドを呼び出した原因と直し方
1 result = None ^ 2 print(result.upper())
Noneに対する属性アクセスはAttributeErrorです。Noneを代入した行ではなく、実際に使った行でエラーになる点に注意が必要です。
C言語: Segmentation fault(NULLポインタの参照)
1 #include <stdio.h> 2 #include <stdlib.h> 3 4 int main(void) { 5 int *p = NULL ; ^ 6 printf("%d\n", *p); 7 return 0; 8 }
NULLポインタの参照はエラーメッセージを一切出さずSegmentation faultでクラッシュします。7言語の中で唯一「原因の手がかりが出ない」言語です。
C#: Object reference not set エラー(null参照)の原因
1 class Program { 2 static void Main(string[] args) { 3 string s = null ; ^ 4 System.Console.WriteLine(s.Length); 5 } 6 }
NullReferenceExceptionという、C#で最も有名な実行時エラーになります。メッセージは「オブジェクト参照が設定されていません」という定型文です。
JavaScript: undefinedのプロパティ読み取りエラーの原因
1 let s = undefined; ^ 2 console.log(s.length);
undefinedのプロパティアクセスはTypeErrorです。値が本当にundefinedになる場面(存在しないプロパティ、範囲外の配列アクセス等)を把握しておく必要があります。
PHP: Call to a member function on null の原因と直し方
1 <?php 2 class Logger { 3 public function log($msg) { echo $msg; } 4 } 5 function getLogger() { return null ; } ^ 6 $logger = getLogger(); 7 $logger->log("hi");
nullへのメソッド呼び出しはFatal errorになり終了します。オブジェクトを取得し損ねた変数をそのまま使うと必ずここで止まります。
TypeScript: 非nullアサーション(!)がコンパイラを騙して実行時エラーになる
1 function shout(s: string): string { 2 return s.toUpperCase(); 3 } 4 const items: string[] = ["a", "b"]; 5 const target: string | undefined = items[5]; ^ 6 console.log(shout(target!));
型システムがnull/undefinedの可能性を追跡してくれますが、!(非nullアサーション)でその検査を自分で無効化すると、JavaScriptと同じ実行時エラーに戻ります。「型が安全」と「実行が安全」は別ものです。
まとめ
静的型付けのTypeScript・C#・Javaでも、実行時に「無い」状態を完全には防げません。TypeScriptの非nullアサーション(!)のように、コンパイラの検査を自分で迂回する構文がある言語では、型システムがあっても油断はできません。共通する対処は「値を使う前に、無い可能性を明示的にチェックする」ことです(if文、Optional、?.、null合体演算子など、道具の名前は言語ごとに違います)。