Javaのラッパークラス（Wrapper classes）は、プリミティブ型に対応する参照型のクラスです。Javaでは、プリミティブ型（int、double、booleanなど）とそれに対応するラッパークラス（Integer、Double、Booleanなど）があります。ラッパークラスは、プリミティブ型をオブジェクトとして扱う必要がある場合や、ジェネリックスやコレクションなどの要求される場合に使用されます。
ラッパークラスには以下のような特徴があります：
プリミティブ型との対応: プリミティブ型にはそれぞれ対応するラッパークラスがあります。たとえば、int型にはIntegerクラス、double型にはDoubleクラスなどです。
イミュータブル（不変）性: ラッパークラスのインスタンスは不変（immutable）です。つまり、一度生成されたらその値を変更することはできません。変更する必要がある場合は新しいインスタンスを生成する必要があります。
Null値の扱い: ラッパークラスは参照型なので、nullを設定することができます。これはプリミティブ型には存在しない概念です。
ユーティリティメソッド: ラッパークラスは、プリミティブ型と関連するユーティリティメソッドを提供します。たとえば、Integerクラスにはint型との変換や文字列からの変換を行うメソッドがあります。
ジェネリックスとの互換性: ラッパークラスはジェネリックスと相性が良く、ジェネリックスを使用する際に便利です。プリミティブ型はジェネリックスの型引数に使用できませんが、ラッパークラスは使用できます。
以下は、プリミティブ型とその対応するラッパークラスです：
ラッパークラスは、それぞれのプリミティブ型と対応する参照型のクラスであり、プリミティブ型とラッパークラス間での相互変換や追加のメソッドを提供します。例えば、java.lang.Integer クラスは int 型の値をラップし、追加のメソッドや int 型への変換メソッドを提供します。
Javaにおける「ボクシング (Boxing)」と「アンボクシング (Unboxing)」とは、プリミティブ型とそれに対応するラッパークラス（Integer、Double、Booleanなど）の相互変換を指します。
Javaのプリミティブ型は、値そのものを扱うための型であり、一方でオブジェクト指向言語であるJavaは、全てのものをオブジェクトとして扱うことができるため、プリミティブ型に対応するオブジェクトが必要になります。そのため、プリミティブ型から対応するラッパークラスへの変換を行う「ボクシング」と、その逆の変換を行う「アンボクシング」が必要になります。
Java 5からは、自動的にボクシングとアンボクシングが行われる「オートボクシング (Autoboxing)」という機能も追加されました。これにより、プリミティブ型とラッパークラスの変換を明示的に行う必要がなくなり、より簡潔なコードが書けるようになりました。
ただし、ボクシングとアンボクシングは、その処理に時間がかかるため、大量のデータを扱う場合にはパフォーマンス上の問題が発生することがあります。そのため、できる限り明示的な変換を行うことで、パフォーマンスを向上させることが望ましい場合もあります。
では、プリミティブ型とボクシング、オートボクシングの違いがパフォーマンスに与える影響を示すコード例を示します。
まず、プリミティブ型を使用した場合のコード例です。
public class PrimitiveExample {
    public static void main(String[] args) {
        int sum = 0;
        for (int i = 1; i <= 1000000; i++) {
            sum += i;
        }
        System.out.println("Sum of 1 to 1000000 using primitive type: " + sum);
    }
}
このコードは、1から1000000までの整数の和を計算し、その結果を出力します。
次に、ボクシングを使用した場合のコード例です。
 
public class BoxingExample {
    public static void main(String[] args) {
        Integer sum = 0;
        for (int i = 1; i <= 1000000; i++) {
            sum += i;
        }
        System.out.println("Sum of 1 to 1000000 using boxing: " + sum);
    }
}
このコードは、同じく1から1000000までの整数の和を計算し、その結果を出力します。ただし、変数 sum の型を Integer にしています。
最後に、オートボクシングを使用した場合のコード例です。
 
public class AutoBoxingExample {
    public static void main(String[] args) {
        Integer sum = 0;
        for (Integer i = 1; i <= 1000000; i++) {
            sum += i;
        }
        System.out.println("Sum of 1 to 1000000 using autoboxing: " + sum);
    }
}
このコードは、同じく1から1000000までの整数の和を計算し、その結果を出力します。ただし、for ループの制御式で Integer 型の変数を使用しています。
これら3つのコードを実行してみると、プリミティブ型を使用した場合が最も高速であることがわかります。一方、ボクシングやオートボクシングを使用した場合は、パフォーマンスが低下する傾向があります。
したがって、パフォーマンスを重視する場合は、可能な限りプリミティブ型を使用することが推奨されます。ただし、可読性や保守性を重視する場合は、ボクシングやオートボクシングを使用することも検討されます。
オートボクシング（Autoboxing）とオートアンボクシング（Unboxing）は、プリミティブ型とその対応するラッパークラス間での自動変換を行う機能です。オートボクシングはプリミティブ型からラッパークラスへの変換を行い、オートアンボクシングはその逆の変換を行います。これにより、プリミティブ型とラッパークラス間の変換が自動的に行われ、コードの記述が簡潔になります。
以下に、オートボクシングとオートアンボクシングの例を示します。
public class Main {
    public static void main(String[] args) {
        // オートボクシング: intからIntegerへの自動変換
        Integer num1 = 10;
        
        // オートアンボクシング: Integerからintへの自動変換
        int num2 = num1;
        
        System.out.println("num1: " + num1); // 出力: num1: 10
        System.out.println("num2: " + num2); // 出力: num2: 10
    }
}
この例では、num1に10という値を代入することで、オートボクシングが行われ、int型の10がInteger型に自動的に変換されます。同様に、num1をint型の変数num2に代入することで、オートアンボクシングが行われ、Integer型の値がint型に自動的に変換されます。
オートボクシングとオートアンボクシングにより、プリミティブ型とラッパークラス間の変換が簡単に行えるため、コードがより読みやすく、効率的になります。
valueOf() メソッドは、ラッパークラス（Integer、Boolean、Double など）の一部で提供される静的メソッドで、指定されたプリミティブ型の値や文字列を対応するラッパークラスのインスタンスに変換します。このメソッドは、プリミティブ型の値や文字列をラッパークラスのオブジェクトに変換するための便利な手段となっています。
一般的な使い方は次の通りです：
Integer num1 = Integer.valueOf(100); // インスタンスの再利用
Integer num2 = Integer.valueOf(100); // インスタンスの再利用
System.out.println(num1 == num2); // true (同一のインスタンスを参照しているか確認)
// プリミティブ型の値からラッパークラスのインスタンスを生成する場合
Integer intValue = Integer.valueOf(10);
Double doubleValue = Double.valueOf(3.14);
Boolean boolValue = Boolean.valueOf(true);
// 文字列からラッパークラスのインスタンスを生成する場合
Integer intValueFromString = Integer.valueOf("123");
Double doubleValueFromString = Double.valueOf("3.14");
Boolean boolValueFromString = Boolean.valueOf("true");
valueOf() メソッドは、プリミティブ型の値や文字列を対応するラッパークラスのインスタンスに変換します。また、このメソッドは、プリミティブ型や文字列の値をキャッシュしており、一定の範囲内で同じ値の場合はキャッシュされたインスタンスを返します。これにより、メモリの効率的な利用とパフォーマンスの向上が期待できます。
Boolean.TRUE と Boolean.FALSE は、Boolean クラスの静的定数であり、それぞれ真と偽を表す Boolean オブジェクトを提供します。これらの定数を使用することにはいくつかのメリットがあります：
明確な意味の表現: Boolean.TRUE と Boolean.FALSE は、その名前から真と偽を明確に表現しています。これにより、コードの可読性が向上し、意図が明確に伝わります。
インスタンスの再利用: Boolean.TRUE と Boolean.FALSE は、Boolean クラスの定数として定義されており、システム全体で同じインスタンスを再利用することができます。これにより、メモリの効率的な利用が可能になります。
オートボクシングの最適化: Boolean.TRUE と Boolean.FALSE を使用することで、オートボクシングによるボクシングおよびアンボクシングのコストを避けることができます。このため、パフォーマンスが向上します。
Boolean.TRUE と Boolean.FALSE を使用することで、真と偽を明確に表現し、パフォーマンスを向上させることができます。
ラッパークラスは、プリミティブ型をオブジェクトとして扱う必要がある場合や、ジェネリック型の場合など、さまざまなユースケースで使用されます。以下に、ラッパークラスの一般的なユースケースをいくつか示します：
List numbers = new ArrayList<>();
numbers.add(10); // プリミティブ型をラッパークラスに自動ボクシングして追加
Map scores = new HashMap<>();
scores.put("Alice", 95); // キーと値としてプリミティブ型をラッパークラスに自動ボクシングして追加
public Integer calculateTotalScore(List scores) {
    // リスト内のスコアの合計を計算
    return scores.stream().reduce(0, Integer::sum);
}
public Integer findMaxValue(List numbers) {
    if (numbers.isEmpty()) {
        return null; // 空のリストの場合はnullを返す
    }
    return Collections.max(numbers);
}
ラッパークラスは、プリミティブ型をオブジェクトとして扱う必要がある場面や、null を許容する場合、ジェネリック型を使用する場合など、さまざまなユースケースで活用されます。