業務備忘録

備忘録です

【Java】Integerってなんなの

2023-08-11 18:42:50 | 日記

1.Integerって何?

標記の通り。

Java習いたての頃からInteger.parseInt()で文字列を数値に変換…といった操作は お手の物であるわけですが、
一方でinteger型の変数に平気で数値リテラルが代入されているのも見かけたりするわけで、じゃあIntegerってint型とは何が違うわけ?という疑問が浮かぶのも当然です。

プリミティブ型はオブジェクトではなく、単なる値であり、それ自身はメソッドを持ちません。
しかし、プログラムの中では、プリミティブ型の値に対する操作(文字列との相互変換など)が必要になる場面がたくさんあります。
そこでJavaは、プリミティブ型を内包し、そのプリミティブ型の値を操作する機能を備えた「ラッパークラス」を提供しています。

Java 本格入門, 2023, 技術評論社

要はコード内で値であるかオブジェクトであるかの違いなんですね〜

2.何ができるの?

メソッド名 機能 コメント
valueOf(int i) 指定されたint値を表すIntegerインスタンスを返す Integerオブジェクトをnewするよりこれを使うほうがいいらしい
compare(int x, int y) 2つのint値を数値的に比較する Mathクラスかと思ってた
comareTo(Integer anotherInteger) 2つのIntegerオブジェクトを数値的に比較する  
intValue() Integerの値をintとして返す  
parseInt(String s)    
toString() Integerの値を表すStringオブジェクトを返します  
フィールド 内容 コメント
MAX_VALUE int型の最大値231-1を表す 桁溢れのチェックに使えそう。
MIN_VALUE int型の最小値-231を表す  

 

3.実際に使ってみる

/new 演算子でIntegerオブジェクトを生成するのはdeprecated
Integer integerTest1 = new Integer(1);
Integer integerTest2 = Integer.valueOf(1);

拡張機能を入れたvsCode上だとnew Integer(1)の部分は線で見せ消ちにされます。deprecatedは非推奨という意味。
valueOfメソッドを使用する場合は、引数が-128〜127の範囲であれば、valueOfメソッドがあらかじめIntegerオブジェクトを予め保存しているため、新たにIntegerオブジェクトを生成せずに済むらしい。
一方new 演算子でコンストラクタを呼び出すと必ずIntegerオブジェクトが生成されるため、メモリを圧迫してしまうとのこと。

ただしこの仕様のせいで挙動に注意が必要らしい。

3.1valueOf()した場合とコンストラクタを呼び出した場合

boolean integerCompared1 = Integer.valueOf(1) == Integer.valueOf(1);
System.out.println("valueOf()の取得結果同士の比較=>" + Boolean.valueOf(integerCompared1));

boolean integerCompared2 = Integer.valueOf(1) == new Integer(1);
System.out.println("valueOf()とnewした場合の比較=>" + Boolean.valueOf(integerCompared2));

3.2結果

valueOf()の取得結果同士の比較=>true
valueOf()とnewした場合の比較=>false

valueOfはキャッシュしてある生成済みのオブジェクトを返すので、valueOfの引数に-128〜127を指定した結果同士を比較した1行目は同じオブジェクトのアドレスを指すことになる。したがって比較結果はtrueとなる。
一方、newした場合は異なるオブジェクトのアドレスを比較するのでfalseとなる。

3.3気をつけましょう

Integerはint型を代入することができる。これは内部的にはInteger.valueOf()してintからIntegerに暗黙的に変換している。
なので、「Integerってint型を代入できるんだ(*^○^*)!ついでに比較して処理をすすめよう!」と考えると痛い目にあうことになる。

Integer integerTest5 = 100;
Integer integerTest6 = 100;
System.out.println(Boolean.toString(integerTest5 == integerTest6));
//true
 
Integer integerTest7 = 999;
Integer integerTest8 = 999;
System.out.println(Boolean.toString(integerTest7 == integerTest8));
//false

こうなる理由は3.2参照

 

3.4比較したいときはどうするの

Integer integerTest7 = 999;
Integer integerTest8 = 999;
System.out.println(integerTest7.compareTo(integerTest8));
//0

compareTo()メソッドを使うことで数値的に比較できる。
2つのオブジェクトを数値的に比較した場合の差を返すので、同じ値の場合は0となる。

とにかくInteger同士を比較演算で比較するのは結構危険そう。

4.Integerの初期値

クラスのフィールドとして、プリミティブ型のintを宣言した場合、初期値は0です。
これに対して、ラッパー型のIntegerを宣言した場合、初期値はnullとなります。
[...]このため、0とデータ型がない状態(空)を区別したい場合は、 ラッパー型を用いる必要があることがわかります。
[...]プリミティブ型を使用していると、値が取得できない場合に0(初期値)となるため、値が指定されていなくて初期値の0となったのか、値として0が指定されていたのかが区別できません。

Java 本格入門, 2023, 技術評論社

なるほど。

 

参考:

https://meetup-jp.toast.com/1808

『Java 本格入門』(2023,技術評論社)