Javaには、Integerというクラスが用意されています。intと関連付けてすでに知っている方もいれば、Java初心者でまだ基礎知識や使い分けがよくわかっていない方もいるでしょう。
そこで、JavaのIntegerの数値を扱う際の概要やメリット、メソッドの使い方などコードの書き方を解説します。
目次
閉じる
1.JavaのIntegerとは
Javaには、Integerクラスと呼ばれるラッパークラスが用意されています。ラッパークラスとは、一般的にプリミティブ型をオブジェクト型で扱うためのクラスです。
Integerは、プリミティブ型のintをラップしてオブジェクトとして整数を扱えます。そのため、オブジェクトでしかアクセスできないクラスやメソッドでもintの数値を利用することが可能です。
ライブラリで使えるIntegerクラス
Integerクラスには、「java.lang.Integer」としてJavaの標準ライブラリが用意されています。Javaの環境を構築した際に、標準ライブラリの機能は自動的にインストールされているため、コード作成時にimportしなくても使うことができるのです。
JavaのIntegerとintの違いを比較
Integerは基本的にintを反映した特徴を持っています。例えば、intの取れる整数値の範囲は、-2147483648から2147483647です。この「2147483647」という数字は32bitで取れる最大値「2の31乗 -1」を示しており、符号の1bitを差し引いた数を意味します。ちなみに、最小値は「-(2の31乗)」で、1を引かずにマイナス符号をつた数です。
Integerで取れる範囲は、intと同じです。しかし、Integerとintには以下の違いがあります。
型の違い
不変の違い
メソッドの有無
nullや継承、Collection格納の可否など
まず、Integerは「参照型」で、intは「プリミティブ型」という違いです。通常、プリミティブ型の変数には数値(実体)がそのまま入っています。しかし、参照型には変数にメモリの位置情報を格納しています。そのため、Integerが保持するのは、intの変数を格納している場所です。
また、Integerは一度、値を格納して決めると後で変更できない「不変」の性質があることです。intはfinalなどの修飾子を付けない限り不変とはならず、後で変更が可能なため、この点も大きく違います。
他にもIntegerにはメソッドが用意されており、クラス機能が使えることも1つの違いです。それから、intにはできないCollection格納の利用がIntegerでは可能となります。Collectionはオブジェクトを格納するため、intでは使えない制約があるのです。
2.JavaのIntegerを使用するメリット
Integerには、intにはない以下の3つのメリットがあります。
メソッドを使用できる
1つ目のメリットは、intでは直接使えないメソッドを使用できることです。メソッドは数値の型変換や最大・最小値を取り出すなど、さまざまな操作を短いコードで簡単に行えます。
例えば、文字列から数値に変換したい場合、Integerを使ってメソッド1つでintの数値に変換できます。
String s = "1"; int num = Integer.parseInt(s); |
しかし、メソッドを使わずにintのみでIntegerのコードを部分実装すると、長くて全体の可読性も悪くなります。
String s = "1"; int num = 0; for (int i = 0; i < s.length(); i++) { num = num * 10 + (s.charAt(i) - '0'); } |
メソッドが使用できることは、コードの短縮と可読性の向上において大きなメリットです。
Collectionを扱える
2つ目のメリットは、ListなどのCollectionを扱えることです。Collectionでは大量の数値をまとめて処理することができます。
Integerを使わずにintで対応すると配列を使用することになり、操作メソッドなどもなく不便です。可変長のサイズ変更もできません。
しかし、Integerで使えるCollectionはそれが可能です。また、Collectionで複雑なデータを管理できるため、複数項目の統計処理やアルゴリズムの実装などにも使えます。
nullを代入できる
3つ目のメリットは、nullを変数に代入できることです。intでは、null代入の処理ができません。Integerが参照型のラッパークラス特有のメリットといえます。
nullを代入できる点は、未入力を明確に区別できるというメリットがあります。そのため、外部データとの連携(未入力がnullとして扱われる場合)やnullチェックによる分岐などがしやすくなります。
キャッシュ機能
4つ目のメリットは、Integerにキャッシュ機能があることです。キャッシュとはWEBなどでも使われる用語ですが、Javaでは直近のデータを装置に記憶して実行時に再利用する機能を指します。
Integerが利用できる整数値のうち、キャッシュされるのは-128から127の範囲です。例えば、a,bの変数にそれぞれ数値を格納して、127と129を代入すると、aはキャッシュされますが、bの値はキャッシュされません。aにはキャッシュ機能が働いたことを意味します。
Integer a = 127; Integer b = 129; |
bの場合は、毎回、新しいインスタンスを作成して数値をオブジェクトに格納します。つまり、キャッシュ機能は使われていません。この違いは、「==」の演算子で比較したい際に明確な違いとなるのです。
Integer a = 127; Integer a2 = 127;
Integer b2 = 129; |
127を入れているIntegerのaとa2は、「a == a2」で比較すると同じメモリ上にあるため、結果が「true」となります。
しかし、範囲外の129を入れているbとb2は、キャッシュ機能が働かないため、「b == b2」の比較をすると結果が「false」となるのです。値は同じでも、メモリ上は違う場所にあると判定されます。
ただし、JVM起動時に「java.lang.Integer.IntegerCache.high」のプロパティ設定を施すことで、上限値を変えることができます。例えば、コマンドプロンプトで以下のような設定をすることです。
java -Djava.lang.Integer.IntegerCache.high=500 YourApp |
上記の場合、整数値の最大が500まで引き上げられ、129も比較の際に同じキャッシュ上で認識されます。
比較時には上限値に注意が必要ですが、キャッシュ機能にはそれを上回るメリットとしてメモリの節約とヒープ領域のオブジェクト生成による逼迫の予防ができます。
関連記事
Java標準ライブラリ&外部ライブラリ一覧ガイド|選び方・使い方・作成方法など解説
3.Java学習でIntegerを使った通常コードの書き方
Javaでは、Integerのコードを書く際に押さえるべきポイントがあります。
まず、以下の足し算をするだけのシンプルなコードは、内部で行われる自動変換(オートボクシング、アンボクシング)やキャッシュ機能を理解する参考になることです。
public class Main { public static void main(String[] args) { Integer a = 127; Integer b = 129;
} } |
例えば、「オートボクシング」は、Javaのコンパイラがintの型をIntegerに自動的に変換することを指します。Integerをintに変換する場合は「アンボクシング」と呼ばれています。
上記のコード例では、Integerのローカル変数aに127を入れており、「a + b」で計算する際は、自動的にアンボクシングでintに変換して、数値の計算を実施しているのです。
最後にInteger型のsumを呼び出す際は、オートボクシングでintから変換した値にします。これで、System.out.printlnの機能を使いコンソールに出力します。
ちなみに、自動変換では「Integer a = Integer.valueOf(127);」という方法でvalueOf()を内部で使用します。これはよくある間違いの「new Integer(127)」と書いて毎回インスタンスを作成する方法と区別したものです。実際、Java9以降はnewの書き方は非推奨となっています。
4.JavaでIntegerのメソッドを利用した使い方
次に、Integerのメソッドを利用した使い方を解説します。
JavaのIntegerをメソッドでintと相互変換
Integerには型変換をする際に、自動で変換される場合と、明示的にコード変換を記述して実行する場合があります。
自動変換は、Javaの仕様として「オートボクシング」と「アンボクシング」です。しかし、この自動変換はintとIntegerの間を切り替えるもので、他の型へは変換されません。そのため、文字列などそれ以外の変換はメソッドを使って変換処理する必要があります。
JavaのIntegerをStringに変換
まずはIntegerに格納している数値から文字列への変換です。Integerクラスには、toString() のメソッドが用意されており、これを使用することでその数値(例:数値の「321」)と同じ文字列(例:文字列の「321」)にすることができます。
public class IntegerToString { public static void main(String[] args) { Integer i = 321;
} } |
これは、2つの方法で変換した場合です。また、下記の例では、変数iに321というint型の数字を入れて初期化し、String.valueOf()のメソッドで文字列に変換しています。
public class IntegerToString { public static void main(String[] args) { Integer i = 321;
} } |
文字列の変換方法は、主にtoString()とString.valueOf()の2通りが使われています。
StringからIntegerに変換
次に、文字列からIntegerの型に変換する場合の例です。文字列からの変換にもメソッドが用意されており、valueOf()のメソッドに文字列を入れることで、Integerに変換できます。
public class StringToInteger { public static void main(String[] args) { String str = "456";
} } |
上記の例では、文字列のstr変数に456を入れて、それをvalueOfで直接Integerに変換しています。
もしIntegerではなく、直接intの数値に変換したい場合は、代わりに「parseInt()」というメソッドを使えば、数字はそのままでintに型変換できます。
値の比較
Integerに代入した値や変換後の値を比較したいときは、等価演算子や比較演算子、メソッドを使用して比べます。
同一性
同一性とは、同じオブジェクトか比較することです。オブジェクトがメモリの同じ位置にある場合、同じオブジェクトを参照していることになります。
以下のコードは、キャッシュ機能が使える場合と使えない場合の2パターンの同一性を等価演算子で比較して確認する例です。
public class Main { public static void main(String[] args) { Integer a = 100; Integer b = 100; Integer c = 130; Integer d = 130;
System.out.println(c == d); } } |
上記では、127まではキャッシュ機能で同じオブジェクトを参照するため、コードを実行すると「a == b」は出力結果はtrueとなります。
一方、キャッシュ機能の範囲外(128以上)となるcとdは、等価演算子で比較するとfalseと出るのです。これは、cとdが別のオブジェクトを参照していることを意味します。
Integerのキャッシュ機能が使えないため、別のメモリ上に数値が格納されているのです。したがって、数字が130で同じでも、オブジェクトが違えば同一性は成立しません。
等価性
同一性の比較に対して、等価性の比較では、格納されている数値自体を比較します。簡潔にいえば、数字がどちらも100なら、等価性はtrue(真)となるわけです。
以下のコード例では、等価性を調べるメソッドを使っています。先のaとb、cとdの組み合わせた数値が同じになるか確認しているのです。
public class Main { public static void main(String[] args) { Integer a = 100; Integer b = 100; Integer c = 130; Integer d = 130;
System.out.println(c.equals(d)); } } |
equals()メソッドでは、「A.equals(B)」と引数を入れることで、AとBの値が同じか確認することができます。aとb、cとdをメソッドに入れて出力すると、どちらもtrue(真)と判定します。
同一性の判定では、キャッシュ機能がないcとdだけはオブジェクトが異なるとして「false」を出力しましたが、この等価性判定では数値自体が同じかを確認することが可能です。そのため、メモリ上のオブジェクトが違っていても数値が同じと出力結果からわかります。
大きさをメソッドで比較
メソッドで大きさを判定する場合は、「compareTo()」というメソッドを使って比較した結果を数字「-1」「1」「0」で出すことができます。
public class Main { public static void main(String[] args) { Integer a = 10; Integer b = 20; Integer c = 10;
System.out.println(b.compareTo(a)); System.out.println(a.compareTo(c)); } } |
上記の例では、aよりbが大きく、bよりaが小さく、aとcは同じです。そのため、-1、1、0と出力されます。
compareTo()のメソッドが数字で出力する機能を持つ理由は、戻り値に配慮していることにあります。
通常、真偽値などの判定はtrueかfalseで出力されて、2パターンまでしか表現できません。しかし、compareTo()は数字で値を返すため、3パターンまで表現することができます。そのため、戻り値の用途が広がり真偽値だけでは表現できない柔軟なプログラムにも応用しやすいのです。
注意点としては、Integerの比較に比較演算子「>=」「>」「<」の記号が使えないことです。Integerでも自動機能を前提に記号を置くことはできますが、比較判定自体は変換前にはできません。
そのため、まずIntegerでは自動的にアンボクシング機能で、記号の使えるプリミティブ型のintに変換されて処理されます。しかし、intに変換されてしまうと、プリミティブ型はnullを取れないため、「NullPointerException」のエラーが出ることです。
したがって、比較演算子の記号は使わず、compareToメソッドの使用がおすすめとなります。
最大値・最小値
変数に入れた数字の大きさが最大値か最小値かを調べる場合は、Javaに標準ライブラリとして搭載されているMathクラスのメソッドを使います。
以下は、2つの数値をMath.max(A, B)、 Math.min(A, B)のAとBに変数や数字を入れることで、maxなら最大値、minなら最小値を返して出力できます。
public class Main { public static void main(String[] args) { Integer a = 150; Integer b = -50;
Integer min = Math.min(a, b);
System.out.println("最小値: " + min); } } |
上記の例では、2つの数字から1つの最大値を出すものです。しかし、3つ以上の変数や数字がある場合もあります。その際は、以下のように、3つ、4つ、5つと増やしてもmaxメソッドをネスト(入れ子構造化)することで対応可能です。
3つの変数
Integer max = Math.max(a, Math.max(b, c)); Integer min = Math.min(a, Math.min(b, c)); |
4つの変数
Integer max = Math.max(Math.max(a, b), Math.max(c, d)); Integer min = Math.min(Math.min(a, b), Math.min(c, d)); |
5つの変数
Integer max = Math.max(Math.max(Math.max(a, b), Math.max(c, d)), e); Integer min = Math.min(Math.min(Math.min(a, b), Math.min(c, d)), e); |
5.JavaのCollectionを活用した使い方
最大値の例では複数の変数をネストすることで対応していましたが、数が多くなるとコードが煩雑になります。そのため、読みやすくするために、ListのようにCollectionを活用してコードをシンプルに記述する方法が有効です。
以下は、Collectionでよく使われるListとMapのIntegerの使い方となります。
Listを使った要素を呼び出して使う例
まずはCollectionのListを使って「List<Integer>」のように値の要素を格納して操作する方法です。
以下の例では、要素の出力、合計値の計算と最大値・最小値などをコードにしています。
import java.util.ArrayList; import java.util.Collections; import java.util.List;
public static void main(String[] args) { List<Integer> numbers = new ArrayList<>();
numbers.add(20); numbers.add(30);
System.out.println("最初の要素: " + numbers.get(0)); int sum = 0; for (Integer num : numbers) { sum += num; } System.out.println("合計: " + sum); int max = Collections.max(numbers); int min = Collections.min(numbers);
System.out.println("最小値: " + min); } } |
計算では、合計値を出すために拡張for文を使って1つずつ足すことで合計値を出します。また、最大値と最小値はCollectionsクラスのmax・minメソッドの使用が効果的です。
そこにListの変数名を指定することで、複数の変数をネストして比較することなく、最大値と最小値を出すことができます。
Mapを使った活用例
次に、Mapを使った複数の値を扱う場合です。Mapでは値をIDと紐づけて要素を入れることができます。
以下は、IDと商品金額を紐づけて、ID指定による金額の出力や売上比較をできるようにしたコード例です。
import java.util.HashMap; import java.util.Map;
public static void main(String[] args) {
Integer id2 = 102; Integer id3 = 103;
salesData.put(id2, 7000); salesData.put(id3, 3000);
if (salesData.containsKey(targetId)) { Integer amount = salesData.get(targetId); System.out.println("ID " + targetId + " の売上額: " + amount + " 円"); }
for (Map.Entry<Integer, Integer> entry : salesData.entrySet()) { Integer id = entry.getKey(); Integer amount = entry.getValue(); System.out.println("ID: " + id + ", 売上額: " + amount + " 円"); }
Integer amount2 = salesData.get(id2); int result = amount1.compareTo(amount2); System.out.println("\nID " + id1 + " と ID " + id2 + " の売上比較: " + (result < 0 ? "少ない" : result > 0 ? "多い" : "同じ")); } } |
まずはIntegerの値として、id1~id3の変数に3桁の顧客IDを入れ、売上金額をセットし、get()メソッドでidから金額を取得します。後は、売上データの表示や、それ以外にもIntegerクラスのメソッドを使ったcompareToによる売上比較などが可能です。
関連記事
JavaのList初期化ガイド|初期化の方法や実装事例、addできない理由なども解説
6.JavaでIntegerを利用するときのよくある質問
ここでは、JavaでIntegerクラスを利用する際によくある質問に回答します。
Integerの意味は?
Integerという単語は、整数を意味する英語です。Javaではこれを「整数型」の意味で使用しています。Javaでは数値を扱う際にintがよく出てきますが、intはintegerの頭文字を取ったもので同じ仲間です。
オートボクシングやアンボクシングを使わずに手動で変換する方法はある?
Javaで自動変換できるオートボクシングやアンボクシングは、自動で処理されます。しかし、nullの扱いや数値の型の対応の仕方が視覚的にわかりにくいでしょう。
そのため、修正・編集やメンテナンスの可読性などに難点があります。その際に知りたいのが手動による変換手段です。
以下にIntegerからintに変換する場合と、その逆にintからIntegerに変換する場合で、それぞれ変換後の型を明示したコードを挙げます。
・Integerからintに変換した場合
public class IntegerToInt { public static void main(String[] args) { Integer i = 200;
int y = i.intValue();
} } |
・intからIntegerに変換した場合
public class IntToInteger { public static void main(String[] args) { int a = 100;
Integer i = Integer.valueOf(a);
} } |
コードは1行増えますが、自動変換の仕組みを考慮しなくても型判別が明確です。
Javaで使うIntegerの初期値は?
Integerの初期値は、オブジェクトの変数の性質に由来しており、フィールド(インスタンス)変数では初期値にnullを取ります。
また、ローカル変数で定義した際は、自動的に初期値が設定されないため、エラーが出ないように初期値の設定が必要です。ちなみに、ローカル変数とはメソッド内で使われる変数のことです。
関連記事
JavaとJavascriptの違いは?文法の特徴から関係性・学習方法まで徹底解説!
Java Goldはどんな資格?難易度や合格率と取得するメリットについて解説
7.まとめ
今回は、Integerクラスの特徴やint自動変換の仕組み、メソッドやその使い方、Collectionでの活用方法などについて解説しました。Integerはintと同じ範囲の整数が取れて、オブジェクトを扱える参照型のラッパークラスです。
intの型で使う場面は自動で相互変換されて、処理できる利便性があります。実際にIntegerを使う場面では、安全性を踏まえて備え付けの比較や等価性判定のメソッドを使用するのが基本です。
しかし、それではコードが複雑になる場合、CollectionのListなどでデータをまとめるとコードがスッキリします。以上を踏まえて、Integerクラスを使いこなしましょう。
本記事が皆様にとって少しでもお役に立てますと幸いです。
「フリーランスボード」は、数多くのフリーランスエージェントが掲載するITフリーランスエンジニア・ITフリーランス向けの案件・求人を一括検索できるサイトです。
開発環境、職種、単価、稼働形態、稼働日数など様々な条件から、あなたに最適なフリーランス案件・求人を簡単に見つけることができます。
単価アップを目指す方や、自分の得意なスキルを活かせる案件に参画したい方は、ぜひ「フリーランスボード」をご利用ください。
自身に最適なフリーランスエージェントを探したい方はこちらよりご確認いただけます。