Javaには、2つの基本的なカテゴリーのタイプがあります:プリミティブ型(直接格納される単純な値)と参照型(オブジェクト。変数はオブジェクトへの参照/ポインタを保持します)。メモリ、代入、比較において大きく異なる動作をします。
8つのプリミティブ型
;
;
;
;
;
;
;
;
プリミティブ型は実際の値を直接格納し、固定サイズで、null になることができず、スタック上に存在します(ローカル変数の場合)。高速でメモリ効率が良いです。
String name = "Ann"; // reference to a String object
int[] arr = {1, 2, 3}; // reference to an array object
List<String> list = new ArrayList<>(); // reference to a List object
Person p = new Person("Bob"); // reference to a Person object
参照変数はヒープ上に格納されたオブジェクトへの参照(メモリアドレス)を保持します — オブジェクト自体ではありません。null にすることができます。
// primitives — assignment COPIES the value (independent)
int a = 5;
int b = a; // b is a COPY
b = 10; // a is still 5
// references — assignment COPIES the reference (both point to the SAME object)
int[] x = {1, 2, 3};
int[] y = x; // y points to the SAME array
y[0] = 99; // x[0] is now 99 too! (shared object)
// == compares VALUES for primitives, but REFERENCES (identity) for objects
String s1 = new String("hi");
String s2 = new String("hi");
s1 == s2; // false — different objects (different references)
s1.equals(s2); // true — equals() compares CONTENT
これは大きな落とし穴です:オブジェクトの == は同一性(同じオブジェクト?)を比較し、内容を比較しません — 内容の比較には .equals() を使用してください。
Integer boxed = 42; // Integer is the OBJECT wrapper for int (autoboxing)
int unboxed = boxed; // auto-unboxing back to primitive
List<Integer> nums; // collections need objects, not primitives
各プリミティブにはラッパークラスがあります(int→Integer など)。こうすることで、プリミティブ型がオブジェクトが必要な場所(コレクション、ジェネリクス)で使用できます。
プリミティブ型と参照型の区別はJavaの基本であり、多くの微妙なバグと動作の原因です:代入はプリミティブ型の場合は値をコピーしますが、オブジェクトの場合は参照を共有します(そのため、共有されているオブジェクトを変更するとすべての参照に影響します)。そして特に重要なのは、オブジェクトの == は同一性を比較します(典型的な間違い — 内容の比較には .equals() を使用してください)。
これを理解することは、比較の正確性、メソッドの引数(オブジェクトは実質的に参照値で渡されます)、null 処理(参照のみが null になる可能性があります)、およびパフォーマンス(プリミティブ型はより軽量です)に影響を与えます。
これはJavaを正しく記述するための基本的な知識です。