オートボクシングは、Javaコンパイラがプリミティブ型とそれに対応するオブジェクトラッパークラスの間で行う自動変換です。たとえば、intを整数に、doubleをDoubleに変換するなどです。変換が逆の場合、これはボックス化解除と呼ばれます。
では、なぜそれが必要なのか、そしてなぜJavaで自動ボックス化とボックス化解除を使用するのでしょうか。
オートボクシングは、Javaコンパイラがプリミティブ型とそれに対応するオブジェクトラッパークラスの間で行う自動変換です。たとえば、intを整数に、doubleをDoubleに変換するなどです。変換が逆の場合、これはボックス化解除と呼ばれます。
では、なぜそれが必要なのか、そしてなぜJavaで自動ボックス化とボックス化解除を使用するのでしょうか。
Integer
持っているparseInt
方法を。int
持っていない。:)
List<Integer>
ますが、持つことはできませんList<int>
。
回答:
この背後にある主な理由を完全に理解するには、いくつかのコンテキストが必要です。
Javaのプリミティブ変数には、値(整数、倍精度浮動小数点2進数など)が含まれます。これらの値の長さは異なる可能性があるため、それらを含む変数の長さも異なる可能性があります(float
対を検討してくださいdouble
)。
一方、クラス変数にはインスタンスへの参照が含まれています。参照は通常、多くの言語でポインター(またはポインターに非常によく似たもの)として実装されます。これらのことは、一般的にかかわらず、彼らが(参照インスタンスのサイズの、同じ大きさを持っているObject
、String
、Integer
、など)。
クラス変数のこのプロパティは、それらに含まれる参照を(ある程度)交換可能にします。これにより、置換と呼ばれるものを実行できます。大まかに言えば、特定のタイプのインスタンスを別の関連するタイプのインスタンスとして使用できます(たとえば、をString
として使用Object
します)。
プリミティブ変数は、相互に、またはObject
。と同じように交換可能ではありません。これの最も明白な理由(しかし唯一の理由ではありません)はそれらのサイズの違いです。これにより、プリミティブ型はこの点で不便になりますが、それでも言語で必要です(主にパフォーマンスに帰着する理由のため)。
ジェネリック型は、1つ以上の型パラメーターを持つ型です(正確な数はジェネリックアリティと呼ばれます)。たとえば、ジェネリック型定義 List<T>
には型パラメーターT
があり、(具象型をObject
生成する)、()、()などになります。 List<Object>
String
List<String>
Integer
List<Integer>
ジェネリック型は、非ジェネリック型よりもはるかに複雑です。彼らは、Java(最初のリリース後)に導入されたとき、JVMへの根本的な変更を行うと、おそらく古いバイナリとの互換性を壊さないようにするために、ジャワの作成者は、少なくとも侵襲的な方法でジェネリック型を実装することを決めた:すべての具体的な種類をList<T>
実際には、(のバイナリに相当する)にコンパイルされます(List<Object>
他のタイプの場合、境界は以外のものになる可能性Object
がありますが、要点はわかります)。このプロセスでは、一般的なアリティと型パラメータの情報が失われるため、型消去と呼びます。
ここで問題は、上記の現実の組み合わせです。 List<T>
List<Object>
すべての場合にになる場合は、T
常にに直接割り当てることができるタイプである必要がありますObject
。それ以外は許可されません。、私たちは前に言ったように、以来int
、float
およびdouble
と互換性がありませんObject
、そこにすることはできませんList<int>
、List<float>
またはList<double>
(ジェネリック医薬品のかなり多くの複雑な実装がJVMに存在していない限り)。
しかし、Javaは次のようなタイプを提供します Integer
、Float
そしてDouble
どのようにそれらを効果的に置換すること、クラスのインスタンスでこれらのプリミティブを包むObject
ように、プリミティブとの間接的な作業にジェネリック型を許可する(あなたがいるためにもすることができます持ってList<Integer>
、List<Float>
、List<Double>
など)。
作成のプロセスInteger
からint
、Float
よりfloat
ようにとは、呼び出されボクシング。その逆は開封と呼ばれます。プリミティブを使用するたびにボックス化する必要があるのObject
は不便なので、言語がこれを自動的に行う場合があります-と呼ばれていますオートボクシングが。
Object
インスタンスとして使用できるように、これらがあります。型消去によるジェネリックスは、その1つのアプリケーションです。
自動ボクシングは、プリミティブデータ型をラッパークラスオブジェクトに変換するために使用されます。ラッパークラスは、プリミティブ型で実行されるさまざまな機能を提供します。最も一般的な例は次のとおりです。
int a = 56;
Integer i = a; // Auto Boxing
それはされて必要なコードを直接記述すると、JVMはボクシングとアンボクシングの世話をすることができるように簡単なので、プログラマの。
自動ボクシングは、java.util.Collectionタイプを操作するときにも役立ちます。プリミティブ型のコレクションを作成する場合、プリミティブ型のコレクションを直接作成することはできません。オブジェクトのコレクションのみを作成できます。例えば :
ArrayList<int> al = new ArrayList<int>(); // not supported
ArrayList<Integer> al = new ArrayList<Integer>(); // supported
al.add(45); //auto Boxing
ラッパークラス
Javaの8つのプリミティブ型(byte、short、int、float、char、double、boolean、long)のそれぞれには、それらに関連付けられた個別のWrapperクラスがあります。これらのWrapperクラスには、プリミティブデータ型で有用な操作を実行するための事前定義されたメソッドがあります。
ラッパークラスの使用
String s = "45";
int a = Integer.parseInt(s); // sets the value of a to 45.
Wrapperクラスが提供する便利な関数はたくさんあります。Javaドキュメントをチェックしてくださいここで
Unboxingは、ラッパークラスオブジェクトをプリミティブ型に変換するAutoBoxingの反対です。これはJVMによって自動的に行われるため、特定の操作にラッパークラスを使用し、プリミティブが処理を高速化するため、それらをプリミティブ型に変換し直すことができます。例えば :
Integer s = 45;
int a = s; auto UnBoxing;
オブジェクトを処理するコレクションの場合、自動ボックス化解除のみが使用されます。方法は次のとおりです。
ArrayList<Integer> al = new ArrayList<Integer>();
al.add(45);
int a = al.get(0); // returns the object of Integer . Automatically Unboxed .
プリミティブ(非オブジェクト)タイプには、効率に正当性があります。
プリミティブ型int, boolean, double
は即時データですが、Object
sは参照です。したがって、フィールド(または変数)
int i;
double x;
Object s;
ローカルメモリ4+ 8 + 8が必要ですか?ここで、オブジェクトの場合、メモリへの参照(アドレス)のみが格納されます。
オブジェクトラッパーInteger, Double
などを使用すると、ヒープメモリ内の整数/倍精度インスタンスへの間接参照を導入できます。
なぜボクシングが必要なのですか?
それは相対的な範囲の問題です。将来のJavaではArrayList<int>
、リフティングプリミティブ型を使用できるようになる予定です。
回答:今のところ、ArrayListはオブジェクトに対してのみ機能し、オブジェクト参照用のスペースを予約し、同様にガベージコレクションを管理します。したがって、ジェネリック型はオブジェクトの子です。したがって、浮動小数点値のArrayListが必要な場合は、doubleをDoubleオブジェクトでラップする必要がありました。
ここで、Javaは、テンプレートが従来のC ++とは異なります。C++クラス vector<string>, vector<int>
は2つのコンパイル製品を作成します。Javaの設計では、すべてのパラメータータイプに新しいコンパイル済み製品を必要とせずに、1つのArrayList.classを使用するようになりました。
したがって、オブジェクトにボックス化しないと、パラメータタイプが出現するたびにクラスをコンパイルする必要があります。具体的には、すべてのコレクションまたはコンテナクラスには、Object、int、double、booleanのバージョンが必要です。Objectのバージョンは、すべての子クラスを処理します。
実際、このような多様化の必要性は、int、char、doubleで動作するIntBuffer、CharBuffer、DoubleBufferなどのJavaSEにすでに存在していました。これらのソースを一般的なソースから生成することで、ハッキーな方法で解決されました。
JDK 5以降、javaには自動ボクシングと自動アンボックスの2つの重要な機能が追加されました。AutoBoxingは、そのようなオブジェクトが必要になるたびに、プリミティブ型が同等のラッパーに自動的にカプセル化されるプロセスです。オブジェクトを明示的に作成する必要はありません。自動ボックス化解除は、カプセル化されたオブジェクトの値が必要なときに型ラッパーから自動的に抽出されるプロセスです。intValue()やdoubleValue()などのメソッドを呼び出す必要はありません。
自動ボックス化と自動ボックス化解除の追加により、アルゴリズムの記述が大幅に簡素化され、値の手動でのボックス化とボックス化解除の餌がなくなります。間違いを避けることも役立ちます。また、オブジェクトのみを操作するジェネリックにとっても非常に重要です。最後に、オートボクシングはコレクションフレームワークでの作業を容易にします。
なぜ(開封)ボクシングがあるのですか?
プリミティブとそのオブジェクト指向(OO)の代替を混合するコードの記述を、より快適で冗長性の低いものにするため。
なぜプリミティブとそのOOの選択肢があるのですか?
プリミティブ型は(C#とは異なり)クラスではないため、のサブクラスではありません Object
はなく、オーバーライドすることはできません。
int
パフォーマンス上の理由からのようなプリミティブと、オブジェクト指向プログラミングの利点のためのObject
ような代替手段がInteger
あり、マイナーな点として、ユーティリティ定数とメソッド(Integer.MAX_VALUEおよびInteger.toString(int)
)の適切な場所があります。
OOの利点は、Generics(List<Integer>
)で最も簡単に確認できますが、これに限定されません。たとえば、次のようになります。
Number getMeSome(boolean wantInt) {
if (wantInt) {
return Integer.MAX_VALUE;
} else {
return Long.MAX_VALUE;
}
}
一部のデータ構造はオブジェクトのみを受け入れることができ、プリミティブ型は受け入れません。
例:HashMapのキー。
詳細については、この質問を参照してください:キーとしてのHashMapとint
データベースの「int」フィールドなど、他にも正当な理由がありますが、これもNULLになる可能性があります。Javaのintをnullにすることはできません。整数参照はできます。自動ボックス化とボックス化解除は、変換の前後に無関係なコードを記述しないようにする機能を提供します。
ArrayListはプリミティブ型をサポートせず、クラスのみをサポートします。ただし、int、doubleなどのプリミティブ型を使用する必要があります。
ArrayList<String> strArrayList = new ArrayList<String>(); // is accepted.
ArrayList<int> intArrayList = new ArrayList<int>(); // not accepted.
Integerクラスは、プリミティブ型intの値をオブジェクトにラップします。したがって、次のコードが受け入れられます。
ArrayList<Integer> intArrayList = new ArrayList<Integer>(); // is accepted.
add(value)メソッドで値を追加できます。文字列値を追加するには、strArrayListコードで「Hello」と言ってください。
strArrayList.add("Hello");
そして、int値を追加して54と言います。
intArrayList.add(54);
しかし、intArrayList.add(54);を書くとき。コンパイラは次の行に変換します
intArrayList.add(Integer.valueOf(54));
intArrayList.add(54)はユーザー側から簡単で受け入れやすいので、コンパイラーは `という難しい仕事をします。intArrayList.add(Integer.valueOf(54));
autoBoxingます。
同様に、値を取得するには、intArrayList.get(0)と入力するだけで、コンパイラ<code>intArrayList.get(0).intValue();
はautoUnboxingに変換します。
オートボクシング:プリミティブ値を対応するラッパークラスのオブジェクトに変換します。
ボックス化解除:ラッパータイプのオブジェクトを対応するプリミティブ値に変換します
// Java program to illustrate the concept
// of Autoboxing and Unboxing
import java.io.*;
class GFG
{
public static void main (String[] args)
{
// creating an Integer Object
// with value 10.
Integer i = new Integer(10);
// unboxing the Object
int i1 = i;
System.out.println("Value of i: " + i);
System.out.println("Value of i1: " + i1);
//Autoboxing of char
Character gfg = 'a';
// Auto-unboxing of Character
char ch = gfg;
System.out.println("Value of ch: " + ch);
System.out.println("Value of gfg: " + gfg);
}
}