PR

Javaのラッパークラス:初心者でもわかる基本概念を3分で解説

Java

Javaの学習を進めていくと、必ず耳にするのが「ラッパークラス(Wrapper Class)」という概念です。ラッパークラスとは、Javaのプリミティブ型(intやdoubleなど)をオブジェクトとして扱うためのクラスの総称です。

前提知識 プリミティブ型 / オブジェクトとは?(クラスとは?)

なぜプリミティブ型をわざわざオブジェクトにする必要があるのか、どのように使うのが正しいのか、一見複雑に感じるかもしれませんが、Javaのコレクションフレームワークを使う上でも、ラッパークラスの知識は不可欠です。

このページでは、Javaのラッパークラスを初心者向けに1から順を追ってわかりやすく解説します。まずはプリミティブ型の復習から始め、ラッパークラスがなぜ必要なのかを明らかにし、その後、各種ラッパークラスの特徴やオートボクシングとアンボクシングの仕組みまで詳しく説明します。

スポンサーリンク

前提知識の復習:プリミティブ型とオブジェクト

Javaには、大きく分けて「プリミティブ型」と「参照型」の2種類のデータ型があります。プリミティブ型は、いわゆる基本的な型(intやdoubleなど)であり、値そのものをメモリ上に直接格納する仕組みになっています。一方、オブジェクトとして扱われるのは参照型であり、クラスによって定義されるインスタンスのメモリアドレスを参照する形で取り扱います。

プリミティブ型の種類

Javaのプリミティブ型は以下の8種類に分類されます。

  1. byte:8ビット整数(-128~127)
  2. short:16ビット整数(-32768~32767)
  3. int:32ビット整数(約-21億~21億)
  4. long:64ビット整数(非常に大きな範囲)
  5. float:単精度浮動小数点数(32ビット)
  6. double:倍精度浮動小数点数(64ビット)
  7. char:文字型(実体は16ビットのUnicode)
  8. boolean:真偽値(trueまたはfalse)

これらは、Java言語の中核を支える基本的なデータ型です。プログラムでよく使われるのがintdouble、そして真偽を扱うbooleanでこれは何となく暗記できている方も多いかもしれません。

参照型(オブジェクト)の特徴

プリミティブ型以外のもの、すなわちクラスとして定義されたオブジェクトは「参照型」と呼ばれます。たとえばStringや自作のクラスなどがこれにあたります。参照型では、変数に格納されているのはインスタンス(オブジェクト)のアドレス(参照先)であり、実際のオブジェクトの中身はヒープ領域などに保存されます。

なぜプリミティブ型をオブジェクトにする必要があるのか?
ここで疑問に思う方もいるかもしれません。プリミティブ型は値を直接扱えるので操作も高速ですし、わざわざオブジェクトに変換する必要などないのでは?

Javaではコレクション(ListやSetなど)の要素として扱う際、オブジェクト以外は格納できません。つまり、プリミティブ型だけではコレクションフレームワークと連携できないのです。この問題を解決するのがラッパークラスになります。

ラッパークラス(Wrapper Class)とは

ラッパークラス(Wrapper Class)とは、先ほど述べたプリミティブ型をオブジェクトとして扱うためのクラスです。たとえばintであればIntegerクラス、doubleであればDoubleクラスといった具合に、プリミティブ型に対応したクラスが標準ライブラリとして用意されています。

具体的には、以下がその対応表です。

  • byteByte
  • shortShort
  • intInteger
  • longLong
  • floatFloat
  • doubleDouble
  • charCharacter
  • booleanBoolean

先頭を大文字にしたもの(int と char だけは例外)と覚えればOKです。

ラッパークラスはすべてjava.langパッケージに存在するため、特別なインポートを行わなくてもすぐに利用可能です。たとえばIntegerクラスのインスタンスを使えば、intの値をオブジェクトとして扱うことができ、コレクションの中にIntegerのインスタンスを格納して管理するといった使い方ができます。

オートボクシングとアンボクシング

Java 1.5(Java 5)以降では、オートボクシング(自動的にプリミティブ型を対応するラッパークラスへ変換)とアンボクシング(ラッパークラスを自動的にプリミティブ型へ変換)がサポートされています。これにより、ラッパークラスとプリミティブ型を意識せずに扱える場面が増え、コードが簡潔になりました。

オートボクシング(Auto-boxing)

以下のようなコードを書いた場合、Javaコンパイラは自動的にint型をInteger型へ変換します。

int num = 10;
Integer numObj = num; // 自動で new Integer(num) と同等の処理が行われる

昔のJava(1.4以前)では、明示的にInteger numObj = Integer.valueOf(num);と書く必要がありましたが、今ではオートボクシングのおかげで、初心者でも直感的にプリミティブ型とラッパークラスを扱えるようになっています。

アンボクシング(Unboxing)

逆に、ラッパークラスからプリミティブ型へ変換することをアンボクシングといいます。例えば、Integer numObjint型として使用したい場合、次のように自動でアンボクシングが行われます。

Integer numObj = 100;
int n = numObj; // 自動で numObj.intValue() が呼び出される

これもJava 1.5以前のコードでは、メソッド呼び出しを明示的に行わなければいけませんでした。

何となく、プリミティブ型をオブジェクトとして扱えるようにしたのがラッパークラスなんだな!と理解できたところで、ここから具体的な利用方法の例をお示ししていきます。

各ラッパークラスの特徴と使い方

ここでは8種類のプリミティブ型に対応するラッパークラスを、ひとつひとつ取り上げて解説します。それぞれがどのような用途やメソッドを持っているかを理解しておきましょう。

Byteクラス

  • プリミティブ型:byte
  • ラッパークラス:Byte
  • 主な範囲:-128~127

Byteクラスは範囲が非常に限られているため、あまり使われる機会は多くありません。ただし、ネットワーク通信やバイナリデータを扱う際には、byte配列を用いることが一般的なので、その際にByteを扱うこともあります。

byte b = 10;
Byte bObj = b; // オートボクシング

byte b2 = bObj; // アンボクシング

Shortクラス

  • プリミティブ型:short
  • ラッパークラス:Short
  • 主な範囲:-32768~32767

shortを使う場面もそこまで多くはありませんが、メモリを節約したい場合に利用されることがあります。ただし、Javaではintが最も一般的に使われる整数型なので、Shortが活躍する場面は限定的。

short s = 100;
Short sObj = s;
short s2 = sObj;

Integerクラス

  • プリミティブ型:int
  • ラッパークラス:Integer
  • 主な範囲:約 -2,147,483,648~2,147,483,647

int型はJavaで最も頻繁に使われる整数型であり、対応するIntegerクラスも非常に利用価値が高いです。Integerには、様々な静的メソッド(valueOf(), parseInt(), toString()など)が用意されており、文字列から整数への変換や整数同士の比較などで重宝します。

int i = 123;
Integer iObj = i; // オートボクシング

// 文字列をintに変換
String str = "456";
int parsed = Integer.parseInt(str);

// intを文字列に変換
String str2 = Integer.toString(i);

Longクラス

  • プリミティブ型:long
  • ラッパークラス:Long
  • 主な範囲:非常に広い(-2^63~2^63-1)

より大きな整数を扱いたいときに使用するのがlong型とLongクラスです。特に、Javaのバージョンによっては、日時を扱う際にUNIXタイムスタンプなどをlongで管理するケースもあります。

long l = 10000000000L;
Long lObj = l;
long l2 = lObj;

Floatクラス

  • プリミティブ型:float
  • ラッパークラス:Float
  • 精度:単精度浮動小数点数(約6~7桁)

浮動小数点数を扱う際にはdoubleのほうが精度が高いため、floatFloatはそれほど頻繁には使われません。ただし、グラフィック系のプログラムや、大量の小数をやり取りする場合にメモリ使用量を抑える目的で用いられることがあります。

float f = 3.14f;
Float fObj = f;
float f2 = fObj;

Doubleクラス

  • プリミティブ型:double
  • ラッパークラス:Double
  • 精度:倍精度浮動小数点数(約15~16桁)

doubleは浮動小数点数の中で最も一般的に使われる型で、計算やデータ処理でもよく登場します。DoubleクラスではparseDouble(), toString()といった便利な静的メソッドが提供されています。

double d = 3.14159265;
Double dObj = d; // オートボクシング
double d2 = dObj;

Characterクラス

  • プリミティブ型:char
  • ラッパークラス:Character
  • 文字コード:UTF-16 (Unicode)

charは1文字を表すのに使われますが、実際にはUnicodeを16ビットで扱います。Characterクラスには、文字が数字かアルファベットかを判定するようなメソッド(isDigit(), isLetter()など)が用意されています。

char c = 'A';
Character cObj = c;
char c2 = cObj;

Booleanクラス

  • プリミティブ型:boolean
  • ラッパークラス:Boolean
  • 値:trueまたはfalse

Booleanは真偽値のラッパークラスです。論理型をコレクションに格納したり、nullを扱いたいときなどに使用されます。booleanをそのまま使うよりも、オブジェクトとしての柔軟性が高いのが特徴です。

boolean flag = true;
Boolean flagObj = flag;
boolean flag2 = flagObj;

ラッパークラスの実践的な使い方

ここでは、実際にラッパークラスとコレクションを組み合わせて使う例を紹介します。多くの場合、ラッパークラスを扱うシーンとして頻出するのが、List<Integer>List<Double>など、コレクションフレームワークとの連携です。

import java.util.ArrayList;
import java.util.List;

public class WrapperClassExample {
    public static void main(String[] args) {
        // intのリストを作成したい場合
        // intはプリミティブ型なので直接は扱えない ⇒ Integerでラップする
        List<Integer> intList = new ArrayList<>();

        // オートボクシングによって自動的にIntegerに変換される
        intList.add(10);
        intList.add(20);
        intList.add(30);

        // リストから値を取り出すときはアンボクシングされ、intとして取得できる
        for (int value : intList) {
            System.out.println("値: " + value);
        }

        // Doubleを使った例
        List<Double> doubleList = new ArrayList<>();
        doubleList.add(3.14); // オートボクシングでDoubleに
        doubleList.add(2.71828);

        for (double d : doubleList) {
            System.out.println("浮動小数点数: " + d);
        }
    }
}

このサンプルでは、オートボクシングとアンボクシングが自然に使われています。もしオートボクシングがなければ、それぞれInteger.valueOf(10)などと明示的に記述する必要があるでしょう。オートボクシングが導入されてからは、プリミティブ型とラッパークラス間の煩雑な変換作業が大幅に削減され、コードの可読性も上がっています。

ラッパークラス使用時の注意点

パフォーマンスへの影響

オートボクシングやアンボクシングは便利ですが、その都度オブジェクトの生成が行われたり、メソッド呼び出しを経由したりするため、プリミティブ型を直接扱う場合よりもパフォーマンスが低下する可能性があります。大量の数値演算を行うような場合は、ラッパークラスよりもプリミティブ型を優先的に使うほうが望ましいでしょう。

nullの取り扱い

ラッパークラスはオブジェクトであるため、nullを代入することが可能です。一方、プリミティブ型にはnullを入れることはできません。この違いは、プログラムにバグを生みやすい要因となります。たとえばIntegernullの場合にアンボクシングを行うと、NullPointerExceptionが発生してしまう可能性があります。

値の比較方法

ラッパークラスのインスタンス同士を==演算子で比較すると、オブジェクトの参照先が等しいかどうかを判定することになります。数値として等しいかどうかを判定したい場合は、equals()メソッドを使う必要があります。例えばIntegerクラスなら以下のようになります。

Integer a = 100;
Integer b = 100;
System.out.println(a == b);      // trueになる場合もあればfalseになる場合も(値のキャッシュ機構による)
System.out.println(a.equals(b)); // true(値が同じ場合)

Javaでは-128127の範囲をキャッシュする機能があるため、値によっては==演算子でtrueが返ることがありますが、仕様に依存した挙動なので注意が必要です。正確な値比較を行う場合は常にequals()か、プリミティブ型へのアンボクシング後に==で比較することを推奨します。

よくある疑問とベストプラクティス

Q
いつラッパークラスを使うべきか?
A
  • コレクション(List, Set, Mapなど)にプリミティブ型を格納したいとき
  • メソッドの引数や戻り値としてnullを扱いたいとき(プリミティブ型ではnullは扱えない)
  • ライブラリ側がラッパークラスを要求する場合(リフレクションなど)

このように、オブジェクトとして扱う必要がある場面ではラッパークラスを積極的に使います。一方、大量の数値計算やパフォーマンスが重要な場面ではプリミティブ型を使うのがベターです。

Q
ラッパークラス間の変換はできる?
A

Javaの標準ライブラリには、ラッパークラス間での直接的な変換メソッドはあまり用意されていません。たとえばIntegerからDoubleへの直接変換メソッドは存在せず、いったんプリミティブ型のintにアンボクシングした後でdoubleにキャストし、それをDoubleにオートボクシングする、という手順が必要になる場合があります。

Integer i = 10;
Double d = i.doubleValue(); // Integer → int → double → Double
Q
Stringとの相互変換は?
A

数値を文字列に変換する場合、ラッパークラスのtoString()String.valueOf()、あるいはInteger.toString(int value)などの静的メソッドを活用します。逆に文字列から数値への変換には、parseInt(), parseDouble()などが用いられます。

String str = "100";
int value = Integer.parseInt(str); // 文字列からintへ
String str2 = String.valueOf(value); // intから文字列へ
タイトルとURLをコピーしました