感謝のプログラミング 10000時間

たどり着いた結果(さき)は、感謝でした。

数値の変換と比較

<スポンサーリンク>

■変換について

Javaには数値基本型に対応する数値クラスが用意されている。

基本型 数値クラス
java.lang.Boolean boolean
java.lang.Character char
java.lang.Byte byte
java.lang.Short short
java.lang.Integer int
java.lang.Long long
java.lang.Float float

数値クラスはnewでオブジェクト化するよりも、valueOfメソッドを使うことが望ましいとされている。
なぜなら、valueOfメソッドを使うと、同じ値に対して同じオブジェクトを再利用できる可能性があるから。
※「パーフェクトJava」の269ページ参照

Integer i = Integer.valueOf(1);

Integer i = new Integer(1);

下の例だといちいち新しい「new Integer(1)」がインスタンス化されるけど、上だと既にインスタンスがある場合、再利用できるという意味だろう。


■比較
同値性の判定について。

数値オブジェクトの比較はequalsを使う。
そうじゃないと、正確な値の比較ができない。
数値オブジェクトは、絶対値が小さい場合は高速化のために同じ値の数値に同じ数値オブジェクトを使いまわす実装になっているが、
絶対値が大きい場合は別のオブジェクトを作成するので、「==」で比較しても値を正しく比較できない。
「==」は「同じインスタンスを参照しているかどうか?」を比較するものだからである。

実際にサンプルを見てみよう。

package sample;

public class Example {

	public boolean compare(Integer i1, Integer i2) {
		if (i1 == i2) {
			return true;
		} else {
			return false;
		}
	}

	public boolean compareEquals(Integer i1, Integer i2) {
		if (i1.equals(i2)) {
			return true;
		} else {
			return false;
		}
	}
}

上の例では、Integerオブジェクトを「==」と「equalse」で比較するメソッドを書いている。

で、色んな値を投入してみると、
・intとIntegerを「==」で比較するとfalse
→ちなみに、数値リテラルは内的にInteger.valueOf(0)が自動的に実行されて、Integerオブジェクトを生成する。

Integer i = 0;

これを「ボクシング変換」という。

逆に、数値オブジェクトから基本型数値への変換をアンボクシング変換という。

・intとIntegerを「equals」で比較すると値が比較されてtrue

・Integer同士でも絶対値が小さい場合は「==」で比較できる

などがわかる。
以下、投入例。JUnitを回している。

package sample;

import static org.hamcrest.CoreMatchers.*;
import static org.junit.Assert.*;

import org.junit.Test;

public class ExampleTest {

	@Test
	public void intとIntegerの同じ数値を比較する() {
		Example ex = new Example();

		int i1 = 1;
		Integer i2 = new Integer(1);
		boolean expected = false;

		assertThat(ex.compare(i1, i2), is(expected));
	}

	@Test
	public void intとIntegerの同じ数値をequalsで比較する() {
		Example ex = new Example();

		int i1 = 1;
		Integer i2 = new Integer(1);
		boolean expected = true;

		assertThat(ex.compareEquals(i1, i2), is(expected));
	}

	@Test
	public void Integer同士でも絶対値が大きい場合は同値性判定ができない例() {
		Integer i1 = 65536;
		Integer i2 = 65536;

		boolean expected = false;
		Example ex = new Example();

		assertThat(ex.compare(i1, i2), is(expected));
	}

	@Test
	public void equalsならちゃんと比較できる() {
		Integer i1 = 65536;
		Integer i2 = 65536;

		boolean expected = true;
		Example ex = new Example();

		assertThat(ex.compareEquals(i1, i2), is(expected));
	}

	@Test
	public void でも絶対値が小さい場合は同値性判定ができる() {
		Integer i1 = 1;
		Integer i2 = 1;

		boolean expected = true;
		Example ex = new Example();

		assertThat(ex.compare(i1, i2), is(expected));
	}


}

<参考にした本>
パーフェクトJava (PERFECT SERIES) (PERFECT SERIES 2)