今日、findbugs を使用してプロジェクトをスキャンしたところ、非常に一般的な脆弱性の 1 つは、2 つの Long または Integer を比較する際の == の直接使用です。 実際、これは間違いです。
Long と Ineger は両方ともパッケージング タイプであり、オブジェクトであるためです。 通常の型 long と int の代わりに、比較するときに等しい値を使用する必要があります。または、最初にlongValue() または intValue() メソッドを使用して基本的な型の値を取得し、次に == を使用して比較することもできます。
しかし、実際には、Long と Integer の両方が -128 ~ 127 のオブジェクトをキャッシュします。 Long 型のソース コードに LongCache クラスがあることがわかります。コードは次のとおりです。
private static class LongCache { private LongCache(){} static final Long cache[] = new Long[-(-128) + 127 + 1]; static { for(int i = 0; i < cache.length; i++) cache[i] = new Long(i - 128); } }
まず、この例を見てください:
public class Test05 { public static void main(String[] args) { Long a = 5L; Long b = 5L; System.out.println("a == b ? " + (a == b)); Long c = 129L; Long d = 129L; System.out.println("c == d ? " + (c == d)); } }
出力された結果は次のとおりです:
a == b ? true c == d ? false
理由
まず、Long a = 5L ; がどのように基本型 Long をオブジェクト Long にラップするかを見てみましょう。
テスト クラスを作成し、それを逆コンパイルして、Java が Long a = 5L のようなコマンドをどのように解析するかを確認できます。
テストクラスは次のとおりです:
public class Test06 { Long l = 3L; }
次に、 javap -verbose Test06 を使用して逆コンパイル結果を確認します。 以下は出力部分です:
{ java.lang.Long l; public com.spring.test.Test06(); Code: Stack=3, Locals=1, Args_size=1 0: aload_0 1: invokespecial #10; //Method java/lang/Object."<init>":()V 4: aload_0 5: ldc2_w #12; //long 3l 8: invokestatic #14; //Method java/lang/Long.valueOf:(J)Ljava/lang/Long; 11: putfield #20; //Field l:Ljava/lang/Long; 14: return LineNumberTable: line 3: 0 line 5: 4 line 3: 14 LocalVariableTable: Start Length Slot Name Signature 0 15 0 this Lcom/spring/test/Test06; }
コードの 8 から、呼び出しが行われていることがわかります。 Long のクラスメソッドは Long.valueOf(Long) であるため、導き出される結論は、Long a = 5L は実際には Long a = Long.valueOf(5); に等しいということです
それでは、 Long.valueOf() メソッドが定義されています:
public static Long valueOf(long l) { final int offset = 128; if (l >= -128 && l <= 127) { // will cache return LongCache.cache[(int)l + offset]; } return new Long(l); }
基本型の値が -128~127 の場合、キャッシュされたオブジェクトを LongCache から直接取得して返します。それ以外の場合は、新しい Long オブジェクトが返されます。
Test05 プログラムの実行結果を理解するのは難しくありません。a と b は -127 ~ 128 の範囲で 5 に等しいため、両方とも LongCache から直接返された Long オブジェクトであるため、== を使用しています。比較の場合、それらは等しく (オブジェクト型の場合、== はヒープ内のアドレスを指す 2 つのオブジェクトの参照を比較します)、c と d は -127 ~ 128 の間ではなく 129 に等しいため、それぞれ 2 です。 new new によって生成された Long オブジェクトは、== を使用して比較すると当然等しくなくなります。
Long は、equals メソッドを書き換えます:
public boolean equals(Object obj) { if (obj instanceof Long) { return value == ((Long)obj).longValue(); } return false; }
まず、.longValue() メソッドを通じて Long オブジェクトの基本型 long の値を取得し、それを比較します。
したがって、Integer と Long の比較では、希望する結果が確実に得られるように、equals を使用するのが最善です。
Integer は Long と同じなので、ここでは例を示しません。
Java における Long と Integer のよくある間違いに関する上記の要約は、編集者が共有したすべての内容です。参考にしていただければ幸いです。また、皆様にも PHP 中国語 Web サイトをサポートしていただければ幸いです。
Java における Long と Integer のよくある間違いに関する詳細な記事については、PHP 中国語 Web サイトに注目してください。