こんにちは!あなたはすでにプリミティブ型についてよく知っており、プリミティブ型をよく扱ってきました。 プログラミング、特に Java におけるプリミティブには多くの利点があります。プリミティブはメモリをほとんど消費しないため、プログラムの効率が向上し、値の範囲に明確に分割されます。しかし、Java を学習する過程で、私たちは「Java ではすべてがオブジェクトである」ということを呪文のように何度も繰り返してきました。しかし、プリミティブはこれらの言葉に真っ向から反論します。それらは物体ではありません。では、「すべてのものはオブジェクトである」という原則は誤りなのでしょうか?あまり。Java では、すべてのプリミティブ型には双子の兄弟であるラッパー クラス(
ラッパー クラス オブジェクトは、他のオブジェクトと同様に作成されます。
Wrapper
) があります。ラッパーとは何ですか? ラッパーは、内部にプリミティブの値を格納する特別なクラスです。 ただし、これはクラスであるため、独自のインスタンスを作成できます。これらは実際のオブジェクトでありながら、必要なプリミティブ値を内部に保存します。ラッパー クラスの名前は、対応するプリミティブの名前に非常に似ているか、完全に一致します。したがって、それらを覚えるのは非常に簡単です。
プリミティブ データ型のラッパー クラス | |
---|---|
プリミティブデータ型 | ラッパークラス |
整数 | 整数 |
短い | 短い |
長さ | 長さ |
バイト | バイト |
浮く | 浮く |
ダブル | ダブル |
チャー | キャラクター |
ブール値 | ブール値 |
public static void main(String[] args) {
Integer i = new Integer(682);
Double d = new Double(2.33);
Boolean b = new Boolean(false);
}
ラッパー クラスを使用すると、プリミティブ型が持つ欠点を軽減できます。最も明白なのは、プリミティブにはメソッドがないことです。たとえば、メソッドがないtoString()
ため、数値をint
文字列に変換することはできません。しかし、ラッパークラスを使えばInteger
簡単です。
public static void main(String[] args) {
Integer i = new Integer(432);
String s = i.toString();
}
逆変換にも困難が伴います。数値が含まれていることが確実にわかっている文字列があるとします。ただし、プリミティブ型の場合は、int
文字列からこの数値を取得して数値に変換することはできません。しかし、ラッパー クラスのおかげで、この機会が得られました。
public static void main(String[] args) {
String s = "1166628";
Integer i = Integer.parseInt(s);
System.out.println(i);
}
出力: 1166628 文字列から数値を取得し、それを参照変数に割り当てることができましたInteger i
。ところで、リンクについて。パラメータはさまざまな方法でメソッドに渡されることはすでにご存知でしょう。プリミティブは値によって渡され、オブジェクトは参照によって渡されます。この知識は、メソッドを作成するときに使用できます。たとえば、メソッドが小数を扱う場合、参照渡しのロジックが必要な場合は、 のDouble/Float
代わりにパラメータをメソッドに渡すことができますdouble/float
。さらに、ラッパー クラスには、メソッドに加えて、非常に使いやすい静的フィールドがあります。たとえば、現在、可能な最大数をコンソールに出力し int
、次に可能な最小数を出力するというタスクに直面していると想像してください。 この作業は初歩的なように見えますが、それでも、Google なしでは実行することはほとんどできません。また、ラッパー クラスを使用すると、次のような「日常の問題」を簡単に解決できます。
public class Main {
public static void main(String[] args) {
System.out.println(Integer.MAX_VALUE);
System.out.println(Integer.MIN_VALUE);
}
}
このようなフィールドを使用すると、より重要なタスクから気を散らすことがなくなります。言うまでもなく、数値2147483647 (これはまさに MAX_VALUE) を出力する過程で、入力を間違えても不思議ではありません :) さらに、前の講義の 1 つで、ラッパー クラスのオブジェクトがは不変 (Immutable) です。
public static void main(String[] args) {
Integer a = new Integer(0);
Integer b = new Integer(0);
b = a;
a = 1;
System.out.println(b);
}
出力: 0 参照が元々指していたオブジェクトはа
状態を変更していません。そうでない場合は、値b
も変更されます。と同様にString
、ラッパー オブジェクトの状態を変更する代わりに、まったく新しいオブジェクトがメモリ内に作成されます。Java の作成者はなぜ最終的に言語内にプリミティブ型を維持することに決めたのでしょうか? すべてはオブジェクトである必要があり、プリミティブが表現するものすべてを表現するために使用できるラッパー クラスがすでにあるので、それらを言語に残してプリミティブを削除してはどうでしょうか? 答えは簡単、パフォーマンスです。プリミティブ型は、オブジェクトの多くの「重い」機能がないため、プリミティブと呼ばれます。はい、オブジェクトには便利なメソッドが多数ありますが、それらは必ずしも必要というわけではありません。場合によっては、数値 33、2.62、またはtrue
/の値だけが必要な場合がありますfalse
。オブジェクトのすべての利点が重要ではなく、プログラムの動作に必要ない状況では、プリミティブの方がはるかに優れた機能を発揮します。
自動梱包・自動開梱
Java のプリミティブとそのラッパー クラスの機能の 1 つは自動ボックス化/自動アンボックス化です。 この概念を理解しましょう。あなたも私も以前に学んだように、Java はオブジェクト指向言語です。これは、Java で書かれたすべてのプログラムがオブジェクトで構成されていることを意味します。プリミティブはオブジェクトではありません。ただし、ラッパー クラス変数にはプリミティブ型の値を割り当てることができます。このプロセスはオートボクシングと呼ばれます。同様に、プリミティブ型の変数にラッパー クラスのオブジェクトを割り当てることができます。このプロセスは自動アンボックス化と呼ばれます。例えば:public class Main {
public static void main(String[] args) {
int x = 7;
Integer y = 111;
x = y; // auto unpacking
y = x * 123; // autopacking
}
}
5 行目では、プリミティブ x に、ラッパー クラスのオブジェクトである y の値を割り当てますInteger
。ご覧のとおり、これには追加のアクションは必要ありません。コンパイラはそれを認識しておりint
、Integer
実際には同じことです。これは自動解凍です。6 行目のオートボクシングでも同じことが起こります。オブジェクト y にはプリミティブの値 (x*123) が簡単に割り当てられます。自動梱包の例です。これが、「自動」という言葉が追加された理由です。ラッパー クラスのオブジェクトにプリミティブ参照を割り当てる場合 (またはその逆の場合)、何もする必要はなく、すべてが自動的に行われます。便利ですよね?:) 自動パッキング/自動アンパッキングのもう 1 つの非常に便利な点は、メソッドの動作に現れています。実際、メソッドのパラメータも自動パックと自動アンパックの対象となります。そして、たとえば、そのうちの 1 つが 2 つのオブジェクトを入力として受け取る場合Integer
、そこに通常のプリミティブを簡単に渡すことができますint
。
public class Main {
public static void main(String[] args) {
printNumber(7);//regular int, even without a variable
}
public static void printNumber(Integer i) {
System.out.println("You entered a number" + i);
}
}
出力: 数値 7 を入力しました。 これは逆に動作します。
public class Main {
public static void main(String[] args) {
printNumber(new Integer(632));
}
public static void printNumber(int i) {
System.out.println("You entered a number" + i);
}
}
覚えておくべき重要な点:自動ボックス化とボックス化解除は配列では機能しません。
public class Main {
public static void main(String[] args) {
int[] i = {1,2,3,4,5};
printArray(i);//error, won't compile!
}
public static void printArray(Integer[] arr) {
System.out.println(Arrays.toString(arr));
}
}
オブジェクトの配列を入力として受け取るメソッドにプリミティブの配列を渡そうとすると、コンパイル エラーが発生します。最後に、プリミティブとラッパーをもう一度簡単に比較してみましょう 。
- パフォーマンス上の利点がある
- これらにより、「すべてはオブジェクトである」という原則に違反しないようにできるため、数字、記号、ブール値 true/false がこの概念から外れることはありません。
- 便利なメソッドとフィールドを提供することで、これらの値を操作できる機能を拡張します
- 一部のメソッドがオブジェクトを排他的に操作できる場合に必要
GO TO FULL VERSION