木曜日, 6月 26, 2025
木曜日, 6月 26, 2025
- Advertisment -
ホームニューステックニュース【Java】なぜIntegerは-128から127で == がtrueになるのか #新卒エンジニア - Qiita

【Java】なぜIntegerは-128から127で == がtrueになるのか #新卒エンジニア – Qiita



【Java】なぜIntegerは-128から127で == がtrueになるのか #新卒エンジニア - Qiita

はじめに

この記事ではJavaのIntegerにおいて特定の範囲において必ずtrueになるのがなぜなのかを解説します。

なぜオブジェクトの比較に == を使うのがダメなの?

これは == が同じメモリ位置を参照しているかどうかを比較しているのに対し、 equals() がオブジェクトの中身を比較していることが理由となります。
この事から、Integerはintのラッパークラス(オブジェクト)なので、equals()を使うべきだと言えます。

本題

本来なら equals() を使うのでこの問題はそこまで出てこないと思いますが、
実は -128から127 の範囲でIntegerの比較を行う場合に等価であると判定されます。

public class Main {
    public static void main(String[] args) {
        Integer numberA = 127;
        Integer numberB = 127;
        
        System.out.println(numberA == numberB); // true
        
        Integer numberC = 128;
        Integer numberD = 128;
        
        System.out.println(numberC == numberD); // false
    }
}

なぜ-127から128だと == がtrueになるのか

Java5から IntegerCache と呼ばれる、キャッシュを利用することでInteger型の処理を向上させる機能が導入されました。
これは特定の範囲の整数値において、同じオブジェクトを再利用するというもので、
特定の範囲の整数値というのが -128から127 になります。

IntegerCacheの実装は以下より確認することができます。
https://github.com/openjdk/jdk/blob/jdk-26%2B3/src/java.base/share/classes/java/lang/Integer.java#L915-L985

private static final class IntegerCache {
    static final int low = -128;
    static final int high;

    @Stable
    static final Integer[] cache;
    static Integer[] archivedCache;

    static {
        // high value may be configured by property
        int h = 127;
        String integerCacheHighPropValue =
            VM.getSavedProperty("java.lang.Integer.IntegerCache.high");
        if (integerCacheHighPropValue != null) {
            try {
                h = Math.max(parseInt(integerCacheHighPropValue), 127);
                // Maximum array size is Integer.MAX_VALUE
                h = Math.min(h, Integer.MAX_VALUE - (-low) -1);
            } catch( NumberFormatException nfe) {
                // If the property cannot be parsed into an int, ignore it.
            }
        }
        high = h;

        // Load IntegerCache.archivedCache from archive, if possible
        CDS.initializeFromArchive(IntegerCache.class);
        int size = (high - low) + 1;

        // Use the archived cache if it exists and is large enough
        if (archivedCache == null || size > archivedCache.length) {
            Integer[] c = new Integer[size];
            int j = low;
            // If archive has Integer cache, we must use all instances from it.
            // Otherwise, the identity checks between archived Integers and
            // runtime-cached Integers would fail.
            int archivedSize = (archivedCache == null) ? 0 : archivedCache.length;
            for (int i = 0; i  archivedSize; i++) {
                c[i] = archivedCache[i];
                assert j == archivedCache[i];
                j++;
            }
            // Fill the rest of the cache.
            for (int i = archivedSize; i  size; i++) {
                c[i] = new Integer(j++);
            }
            archivedCache = c;
        }
        cache = archivedCache;
        // range [-128, 127] must be interned (JLS7 5.1.7)
        assert IntegerCache.high >= 127;
    }

    private IntegerCache() {}
}

範囲を決定している箇所

static final int low = -128;
static final int high;

@Stable
static final Integer[] cache;
static Integer[] archivedCache;

static {
    // high value may be configured by property
    int h = 127;
    String integerCacheHighPropValue =
        VM.getSavedProperty("java.lang.Integer.IntegerCache.high");
    if (integerCacheHighPropValue != null) {
        try {
            h = Math.max(parseInt(integerCacheHighPropValue), 127);
            // Maximum array size is Integer.MAX_VALUE
            h = Math.min(h, Integer.MAX_VALUE - (-low) -1);
        } catch( NumberFormatException nfe) {
            // If the property cannot be parsed into an int, ignore it.
        }
    }
    high = h;

IntegerCacheの範囲は $[\mathrm{low}, \mathrm{high}]$ であり、$\mathrm{low} = -128$、$\mathrm{high} = 127$であることがわかります。
この値範囲は JLS5.1.7. Boxing Conversion で定義されています。

If the value p being boxed is true, false, a byte, or a char in the range \u0000 to \u007f, or an int or short number between -128 and 127 (inclusive), then let r1 and r2 be the results of any two boxing conversions of p. It is always the case that r1 == r2.

補足
オプションとして、java.lang.Integer.IntegerCache.high の値を128以上にすることで、上限値を127以上にする事が可能になります。

まとめ

  • IntegerにおいてはJava5から導入されたIntegerCacheによって-128から127の範囲においてオブジェクトがキャッシュされる影響で == がtrueになることを解説しました
  • IntegerCacheの実装によると、上限値は java.lang.Integer.IntegerCache.high を変更することで128以上にすることができます

参考文献





Source link

Views: 0

RELATED ARTICLES

返事を書く

あなたのコメントを入力してください。
ここにあなたの名前を入力してください

- Advertisment -