Kutulu Uzun değerleri 127 ve 128 karşılaştırma


111

Koşulları kullanarak iki Uzun nesne değerini karşılaştırmak istiyorum if. Bu değerler olduğunda az 128 den , ifkoşul düzgün çalışır, ancak olduklarında ya da daha büyük 128 eşit , karşılaştırma başarısız olur.

Misal:

Long num1 = 127;
Long num2 = 127;

if (num1 == num2) {
    // Works ok
}

Yukarıdaki kodda karşılaştırma düzgün çalışıyor, ancak aşağıdaki kodda başarısız oluyor:

Long num1 = 128;
Long num2 = 128;

if (num1 == num2) {
    // Does NOT work
}

Uzun değişkenleri 127'den büyük değerlerle karşılaştırırken neden bir sorun var ? Değişken veri türleri uzun ilkellere değiştirilirse , karşılaştırmalar tüm durumlar için çalışır.

Yanıtlar:


212

TL; DR

Java, -128ile arasındaki kutulu Tamsayı örneklerini önbelleğe alır 127. Değerler yerine ==nesne referanslarını karşılaştırmak için kullandığınızdan , yalnızca önbelleğe alınan nesneler eşleşecektir. Kutusuz ilkel değerlerle çalışın veya nesnelerinizi karşılaştırmak için kullanın .long.equals()Long

Uzun (amaçlanan) versiyon

Uzun değişkeni 127'den büyük değerle karşılaştırmada neden sorun var? Yukarıdaki değişkenin veri türü ilkel (uzun) ise, kod tüm değerler için çalışır.

Java, -128 ile 127 aralığındaki Tamsayı nesne örneklerini önbelleğe alır . Bahsedilen:

  • N Uzun değişkene değeri 127( önbelleğe alınmış ) ayarlarsanız , aynı nesne örneği tüm referanslar tarafından gösterilecektir. (N değişken, 1 örnek)
  • Değeri N Uzun değişkene ayarlarsanız 128( önbelleğe alınmaz ), her referansın işaret ettiği bir nesne örneğiniz olur. (N değişken, N örnek)

Bu yüzden bu:

Long val1 = 127L;
Long val2 = 127L;

System.out.println(val1 == val2);

Long val3 = 128L;
Long val4 = 128L;

System.out.println(val3 == val4);

Şu çıktılar:

doğru
yanlış

İçin 127L bellek (önbelleğe) aynı nesne örneğine Her iki referans (VAL1 ve val2) noktasında bu değer, bu döner true.

Öte yandan, 128 değeri için, bellekte önbelleğe alınmış bir örnek olmadığından, kutulu değerler için yeni atamalar için yeni bir tane oluşturulur ve sonuçta iki farklı durum (val3 ve val4 ile gösterilir) ve geri döner false. aralarında karşılaştırma.

Bunun nedeni yalnızca , ilkel değerleri değil, iki Long nesne referansını operatörle karşılaştırmanızdır. Bu Önbellek mekanizması olmasaydı, bu karşılaştırmalar her zaman başarısız olurdu, bu nedenle buradaki asıl sorun, kutulu değerleri operatörle karşılaştırmaktır .long====

Bu değişkenleri ilkel longtürlere dönüştürmek, bunun olmasını engelleyecektir, ancak kodunuzu Longnesneleri kullanarak tutmanız gerektiğinde , bu karşılaştırmaları aşağıdaki yaklaşımlarla güvenle yapabilirsiniz:

System.out.println(val3.equals(val4));                     // true
System.out.println(val3.longValue() == val4.longValue());  // true
System.out.println((long)val3 == (long)val4);              // true

(Dökümler için bile uygun sıfır kontrolü gereklidir)

IMO , Nesne karşılaştırmalarıyla uğraşırken .equals () yöntemlerine bağlı kalmak her zaman iyi bir fikirdir .

Referans bağlantıları:


15

Java, -128'den 127'ye kadar olan ilkel değerleri önbelleğe alır . İki Long nesnesini karşılaştırdığımızda, java dahili olarak onu ilkel değere çevirin ve karşılaştıralım. Ancak 127'nin üzerinde Uzun nesne tip kastı almayacaktır. Java, çıktıyı .valueOf () yöntemiyle önbelleğe alır .

Bu önbelleğe alma -128'den 127'ye Byte, Short, Long için çalışır. Tamsayı önbelleğe alma için -128'den java.lang.Integer.IntegerCache.high veya 127'den hangisi daha büyükse çalışır. (Hangi Tamsayı değerlerine kadar üst seviye değeri ayarlayabiliriz java.lang.Integer.IntegerCache.high kullanılarak önbelleğe alınmalıdır).

 For example:
    If we set java.lang.Integer.IntegerCache.high=500;
    then values from -128 to 500 will get cached and 

    Integer a=498;
    Integer b=499;
    System.out.println(a==b)

    Output will be "true".

Float ve Double nesneleri asla önbelleğe alınmaz.

Karakter 0'dan 127'ye önbellek alacak

İki nesneyi karşılaştırıyorsunuz. so == operatörü nesne referanslarının eşitliğini kontrol edecektir. Bunu yapmanın aşağıdaki yolları var.

1) her iki nesneyi de ilkel değerlere dönüştür ve karşılaştır

    (long)val3 == (long)val4

2) nesnenin değerini okuyun ve karşılaştırın

    val3.longValue() == val4.longValue()

3) Nesne karşılaştırmasında equals () yöntemini kullanın.

    val3.equals(val4);  

14

num1ve num2Uzun nesnelerdir. equals()Onları karşılaştırmak için kullanmalısınız . ==karşılaştırma bazen JVM kutularının ilkel biçiminden dolayı işe yarayabilir, ancak buna bağlı değildir.

if (num1.equals(num1))
{
 //code
}

1
Bu (daha iyi) veya dönüş değerini karşılaştırın .longValue().
Giulio Franco

4

Java'daki ilkel olmayanları (Nesneler olarak da bilinir) ==karşılaştırmak, değerleri yerine referanslarını karşılaştırır. Longbir sınıftır ve dolayısıyla Longdeğerler Nesnelerdir.

Sorun şu ki, Java Geliştiricileri, insanların uyumluluk sağlamak için eskisi Longgibi kullanmalarını istedi long, bu da özünde özellik olan otomatik kutulama kavramına yol açtı, - longdeğerler - LongNesneler olarak değiştirilecek ve tam tersi gerektiği gibi. Otomatik kutulamanın davranışı, tam olarak belirtilmediği için her zaman tam olarak öngörülebilir değildir.

Bu nedenle, güvenli olmak ve öngörülebilir sonuçlar elde etmek için her zaman .equals()nesneleri karşılaştırmak için kullanın ve bu durumda otomatik kutulamaya güvenmeyin:

Long num1 = 127, num2 = 127;
if(num1.equals(num2)) { iWillBeExecutedAlways(); }
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.