この内容は古いバージョンです。最新バージョンを表示するには、戻るボタンを押してください。
バージョン:8
ページ更新者:guest
更新日時:2026-06-11 07:12:00

タイトル: 型
SEOタイトル: Java 型システム完全ガイド (プリミティブ/参照/Wrapper)

この記事の要点
  • Java の型は大きく プリミティブ型 8 種参照型 (オブジェクト/配列) の 2 系統
  • プリミティブ: byte/short/int/long/float/double/char/boolean — スタックに値そのものを格納
  • 参照型は Wrapper クラス (Integer/Double 等) と AutoBoxing でプリミティブと相互変換
  • == はプリミティブでは値比較、参照型では参照アドレス比較 → 値の等価判定は equals()
  • モダン Java: var (Java 10+ 型推論)、record (Java 14+)、sealed (Java 17+)、generics、enum

Java の型システム概要

Java は静的型付け言語で、変数を宣言した時点で型が決まり、コンパイル時に型チェックが行われます。型は大きく 2 系統に分かれます。

分類格納場所初期値
プリミティブ型int, double, booleanスタック (値そのもの)0 / 0.0 / false
参照型 (オブジェクト)String, List, Userヒープ (アドレス参照)null
参照型 (配列)int[], String[]ヒープnull

プリミティブ型 8 種

ビット範囲リテラル例
byte8-128 〜 127byte b = 100;
short16-32,768 〜 32,767short s = 30000;
int32約 -21.4 億 〜 21.4 億int i = 100;
long64約 ±9.2 × 10^18long l = 100L;
float32IEEE 754 単精度float f = 1.5f;
double64IEEE 754 倍精度double d = 1.5;
char16U+0000 〜 U+FFFF (UTF-16)char c = 'A';
booleanJVM 依存true / falseboolean b = true;

リテラルの書き方

// 整数リテラル
int dec   = 100;        // 10進
int hex   = 0xFF;       // 16進 (255)
int oct   = 0755;       // 8進  (493)  ← 0始まりは8進!
int bin   = 0b1010;     // 2進  (10)   Java 7+
long big  = 10_000_000_000L;  // ★ アンダースコア区切り Java 7+, L 付与必須

// 浮動小数リテラル
double pi = 3.14;
float  f  = 3.14f;      // ★ f を付けないと double と解釈されコンパイルエラー
double exp = 1.5e10;    // 指数表記

// 文字・文字列
char ch  = 'あ';        // UTF-16
String s = "Hello";     // 参照型 (java.lang.String)

// boolean
boolean ok = true;

整数オーバーフロー

Java のプリミティブ整数はオーバーフローしても例外を投げません。ラップアラウンドして無音で間違った値になります。

int max = Integer.MAX_VALUE;     // 2147483647
int over = max + 1;              // -2147483648 ★ 警告なし
System.out.println(over);

// 安全な方法 (Java 8+): Math.addExact は例外を投げる
try {
    int safe = Math.addExact(max, 1);  // → ArithmeticException
} catch (ArithmeticException e) {
    System.out.println("overflow!");
}

// 64bit に拡張して回避
long big = (long) max + 1L;       // 2147483648 OK

// 任意精度
import java.math.BigInteger;
BigInteger huge = new BigInteger("99999999999999999999");

Wrapper クラスと AutoBoxing

プリミティブ型はオブジェクトではないため、List<int> のような Generics には使えません。Wrapper クラスでラップします。

プリミティブWrapper
byteByte
shortShort
intInteger
longLong
floatFloat
doubleDouble
charCharacter
booleanBoolean
// AutoBoxing : プリミティブ → Wrapper を自動変換
Integer wrapped = 100;        // 実際は Integer.valueOf(100)
List<Integer> nums = new ArrayList<>();
nums.add(1);                  // int → Integer 自動変換

// AutoUnboxing : Wrapper → プリミティブ
int n = wrapped;              // 実際は wrapped.intValue()

// ★ 罠1: null の AutoUnboxing → NullPointerException
Integer nullable = null;
int x = nullable;             // → NPE

Object/Wrapper の == と equals

参照型では ==参照アドレスの比較です。値の同一性は equals() を使います。

String a = new String(&quot;hello&quot;);
String b = new String(&quot;hello&quot;);

System.out.println(a == b);        // false (参照が違う)
System.out.println(a.equals(b));   // true  (値が同じ)

// ★ Integer キャッシュの罠
Integer i1 = 127;
Integer i2 = 127;
System.out.println(i1 == i2);       // true  (-128〜127 はキャッシュ)

Integer i3 = 128;
Integer i4 = 128;
System.out.println(i3 == i4);       // false (キャッシュ外、別オブジェクト)
System.out.println(i3.equals(i4));  // true

// ★ null 安全な比較
Objects.equals(a, b);              // どちらも null OK

モダン Java の型機能

var (Java 10+) 型推論

// 右辺から型を推論。ローカル変数のみ。
var list = new ArrayList<String>();   // ArrayList<String>
var map  = new HashMap<String, Integer>();
var i    = 100;                       // int
var s    = "hello";                   // String

// ★ 禁止: フィールド・引数・戻り値には使えない
// var x;  // NG (初期化必須)
// var x = null;  // NG (null は推論不能)

record (Java 14+) 不変データクラス

// 1 行で final フィールド + getter + equals + hashCode + toString が生える
public record Point(int x, int y) {}

Point p = new Point(1, 2);
System.out.println(p.x());           // 1
System.out.println(p);                // Point[x=1, y=2]
System.out.println(p.equals(new Point(1, 2)));  // true

sealed (Java 17+) 継承制限

// 継承できるクラスを permits で限定
public sealed interface Shape permits Circle, Square, Triangle {}

public record Circle(double r) implements Shape {}
public record Square(double side) implements Shape {}
public record Triangle(double base, double h) implements Shape {}

// switch パターンマッチング (Java 21+)
double area = switch (shape) {
    case Circle c   -> Math.PI * c.r() * c.r();
    case Square s   -> s.side() * s.side();
    case Triangle t -> t.base() * t.h() / 2;
};

Generics

// 型パラメータで型安全なコレクション
List<String> names = new ArrayList<>();   // Java 7+ ダイヤモンド演算子
names.add("Alice");
String first = names.get(0);             // キャスト不要

// 自作 Generics
public class Box<T> {
    private T value;
    public T get() { return value; }
    public void set(T value) { this.value = value; }
}

// 境界
public <T extends Comparable<T>> T max(List<T> list) {
    return list.stream().max(Comparator.naturalOrder()).orElseThrow();
}

final と enum

// final 変数 = 再代入不可 (定数)
final int MAX = 100;

// final クラス = 継承不可
public final class Util { ... }

// final メソッド = override 不可
public final void run() { ... }

// enum = 型安全な定数集合
public enum Color {
    RED, GREEN, BLUE;

    public String hex() {
        return switch (this) {
            case RED   -> "#FF0000";
            case GREEN -> "#00FF00";
            case BLUE  -> "#0000FF";
        };
    }
}

Color c = Color.RED;
System.out.println(c.hex());     // #FF0000

FAQ

Q: int と Integer どちらを使う?
A: パフォーマンス重視なら int (プリミティブ)、Collection や Generics、null を許容したい場合は Integer。基本は int を優先。

Q: float と double はどちらが標準?
A: 通常は double を使います。float は 7 桁程度の精度しかなく、金融計算にはBigDecimalを使います。

Q: var を多用すべき?
A: ローカル変数で右辺から型が明らかなら可。new 演算子や明示的キャストとの併用が読みやすい。