非常に抽象的なレベルでは、ラッパー クラスがプリミティブ データ型のオブジェクトを作成することは知っていますが、なぜラッパー クラスを使用する必要があるのか、プリミティブ データ型に対してどのような利点があるのかについて興味がありました。
6 に答える
そもそもコレクション、たとえば、ここでList<Integer>
はプリミティブを使用できませんint
。実際には、次のようなさまざまなオブジェクトタイプで動作できるジェネリッククラス/インターフェイス
public interface Callable<V> {
V call() throws Exception;
}
ラッピングは、新しいInteger(i)ではなく、Integer.valueOf(i)を使用して行うのが最適であることに注意してください。後者は、キャッシュを使用しようとします。アンラップはInteger.intValue()として実行されます。プリミティブのこれらのラッピング/アンラッピングは非常に典型的な操作であるため、Java5は自動ボクシング/アンボクシングを導入しました
List<Integer> list = new ArrayList<>();
list.add(1);
int i = list.get(0);
このコードは、Javaコンパイラによって自動的に次のように変換されます。
list.add(Integer.valueIf(1));
int i = list.get(0).intValue(); // this is where NullPointerException sometimes happens
ラッパー クラスは、プリミティブ型により多くの機能を追加するように設計されているため、コレクション フレームワークを使用してジェネリック コードと互換性があり、その他の多くの利点があります。ただし、それらはプリミティブ型を置き換えるものではありません。
したがって、オブジェクトを作成するとプログラムにかなりのオーバーヘッドが追加されるため、ジェネリックを扱う場合など、必要な場合にのみラッパーを使用する必要があります。したがって、通常はプリミティブに固執する必要があります。
ラッパー型により、プリミティブはより文脈上の意味を保持できます。たとえば、整数は何でもかまいませんが、たとえば Hours と呼ばれるクラスは、使用されている場所に数値の意味を与えます。
また、消費者にとって一貫性のある明白な方法で、前述のプリミティブを変更するメソッドを作成することもできます。この点に関する詳細については、ドメイン駆動設計をご覧ください。
プリミティブ型は値を保持するだけで、ラッパークラスはそれに名前を付けます。
クラス名を使用すると、コンパイラーは静的チェックを実行できます。これにより、インターフェイスがより意味のあるものになります。また、ラッパークラスでいくつかのメソッドを定義して、プリミティブ値を検証することもできます。
通常、小さなプロジェクトの場合、プリミティブ型を使用するのは問題ないと思います。
想像してみてください:ステータスを保存する必要があり、別のコンピューター(同じゲーム)でプレイしたいゲームをプレイしている場合、他のコンピューターにステータス(レベル)を取得することに決めた場合、その状態から続行できます(からではありませんはじめに).. 現在の武器ステータスが 3 の場合の質問に移ります。if(いくつかのレベルをプレイして武器を追加しますが、現在は 3) } しかし、プリミティブが異なるため、オブジェクトとして保存することはできません (スタック内に存在します)。したがって、オブジェクトとして武器が必要です (( solution : create Integer Object)) Integer weapon = new Integer(1){ ... }
ラッパー オブジェクトは通常のオブジェクトであり、参照が存在する可能性がありますnull
。これにより、プリミティブでは不可能な「未設定」状態の使用が可能になります。
Integer no = null; // not set
プリミティブ変数が「未設定」であることを示すには、-1 のような魔法の値を使用する必要があります。