ホームページ  >  記事  >  Java  >  Java における Long と Integer の間のよくある間違いの詳細な要約

Java における Long と Integer の間のよくある間違いの詳細な要約

高洛峰
高洛峰オリジナル
2017-01-22 10:22:231328ブラウズ

今日、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 サイトに注目してください。

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。