「開発者は数値を記述するクラスを思いつくことができたので、実際の開発者のように創造的になろうと決めました。」

「まず、彼らは抽象 Number クラスを思いつきました。そこから Byte、Short、Integer、Long、Float、Double が派生します。このクラスには、数値を他の数値型に変換するのに役立つメソッドがあります。」

Number クラスのメソッド
1
int intValue()
2
long longValue()
3
float floatValue()
4
double doubleValue()
5
byte byteValue()
6
short shortValue()

「そうです。結局のところ、これを書くことはできません。」

Long x = 100000;
Integer y = (Integer) x;

「はい、これらの型はプリミティブではありません。それが、Number クラスのメソッドを使用する理由です。」

Long x = 100000;
Integer y = x.intValue();

「しかし、まだ考慮すべきことがいくつかあります。Integer は int ではないため、Integer オブジェクトを従来の «==» 演算子と比較することはできません。」

プリミティブ型の比較
int x = 500;
int y = 500;
x == y; //true
非プリミティブ型の比較
Integer x = 500;
Integer y = 500;
x == y; //false
x.equals(y); //true

「その通りです。どういうわけか、すぐには思いつきませんでした。」

「しかし、それだけではありません。」

「私の回路をショートさせているんです!他に何があるんですか?」

「int 値を Integer 変数に代入すると、Integer.valueOf メソッドが呼び出されます。」

コード 本当に何が起こるのか
Integer x = 5;
Integer x = Integer.valueOf(5);

「はい、上の例でそれは理解しました。」

「ただし、valueOf 関数は常に新しい Integer オブジェクトを作成するとは限りません。」

「えっと、『いつもではない』ってどういう意味ですか?」

「-128 から 127 までの値をキャッシュします。」

コード 本当に何が起こるのか 説明
Integer x = 300;
Integer y = 300;
Integer z = 300;
Integer x = Integer.valueOf(300);
Integer y = Integer.valueOf(300);
Integer z = Integer.valueOf(300);
変数 x、y、z には異なるオブジェクトへの参照が含まれています
Integer x = 100;
Integer y = 100;
Integer z = 100;
Integer x = Integer.valueOf(100);
Integer y = Integer.valueOf(100);
Integer z = Integer.valueOf(100);
変数 x、y、z には、同じオブジェクトへの参照が含まれています。
Integer x = new Integer(10)
Integer y = new Integer(10)
Integer z = 10;
Integer t = 10;
Integer x = new Integer(10)
Integer y = new Integer(10)
Integer z = Integer.valueOf(10);
Integer t = Integer.valueOf(10);
変数 z と t には、同じオブジェクトへの参照が含まれています。

つまり、状況はこうです。

1)  «new Integer()» を記述すると、新しいオブジェクトを取得することが保証されます。

2)  Integer.valueOf() を明示的にまたはオートボクシングを通じて呼び出した場合、number 引数が -128 から 127 の範囲内にある場合、メソッドは新しいオブジェクトまたはキャッシュされたオブジェクトを返すことがあります。

「キャッシュからオブジェクトを返すメソッドの何がそんなにひどいのでしょうか?」

「気にしないでください。ただ、予期しないときにオブジェクトが等しい場合があることを知っておく必要があります。等しいということはすべて複雑です。プリミティブと非プリミティブを比較する場合、それらはプリミティブとして比較されます。」

比較問題
int x = 300;
Integer y = 300;
Integer z = 300;

x == y; //true (comparison based on primitive value)
x == z; //true (comparison based on primitive value)
y == z; //false (comparison based on references)
さらに興味深い例です。ここにキャッシュが画像に入ります
int x = 100;
Integer y = 100;
Integer z = 100;

x == y; //true (comparison based on primitive value)
x == z; //true (comparison based on primitive value)
y == z; //true (comparison based on references; they point to the same object)
ただし、ここではキャッシュは関係ありません
int x = 100;
Integer y = new Integer(100);
Integer z = 100;

x == y; //true (comparison based on primitive value)
x == z; //true (comparison based on primitive value)
y == z; //false (comparison based on references; they point to different objects)

「すごいですね...それで、これをどうやって覚えたらいいでしょうか?」

「これを暗記する必要はありません。必要なのは、これがどのように構成されているか、そしてプリミティブとそれに対応する非プリミティブが作用したときに実際に何が起こるかを理解することだけです。」

「また、Integer クラスのメソッドを参照することをお勧めします。このクラスには、優れた便利なメソッドが多数あります。そのうちの 1 つを頻繁に使用することもあります。」

「はい、覚えています。Integer.parseInt();」