Подтвердить что ты не робот

Использование оператора == в Java для сравнения объектов-оболочек

Я читаю SCJP Java 6 от Kathy Sierra и Bert Bates, и эта книга меня так запутывает. На стр. 245 указано, что следующий код ниже.

Integer i1 = 1000;
Integer i2 = 1000;
if(i1 != i2)
System.out.println("different objects");

//Prints output
different objects

Затем на самой следующей странице есть следующий код

Integer i3 = 10;
Integer i4 = 10;
if(i3 == i4)
System.out.println("same objects");

//Prints output
same objects

Я так смущен! Когда я пытаюсь это сделать самостоятельно, кажется, что вы не можете использовать == для сравнения так же, как вы бы использовали метод equals(). Использование == всегда дает мне "false", даже если переменные Integer установлены на одно значение (т.е. 10). Я прав? Использование == для сравнения одного и того же объекта Integer (с одинаковыми значениями) всегда приведет к "false"

4b9b3361

Ответ 1

Ключ к ответу называется интернированием объектов. Java ставит небольшие числа (менее 128), поэтому все экземпляры Integer(n) с n в интернированном диапазоне одинаковы. Числа, которые больше или равны 128, не интернированы, поэтому объекты Integer(1000) не равны друг другу.

Ответ 2

Если вы посмотрите на исходный код для Integer, вы увидите, что Integer.valueOf(int) пулы все значения от -128 до 127. Причина в том, что небольшие значения Integer используются часто и, таким образом, достойный объединения/кэширования.

Взято прямо из Integer.java:

public static Integer valueOf(int i) {
    if(i >= -128 && i <= IntegerCache.high)
        return IntegerCache.cache[i + 128];
    else
        return new Integer(i);
}

Обратите внимание, что этот пул является специфичным для реализации и нет гарантии объединенных диапазонов.

Ответы о интернинге верны в концепции, но неверны с терминологией. Интернатура в Java обычно подразумевает, что среда выполнения Java выполняет объединение (например, String intern). В случае Integer это сам класс, который выполняет объединение. Там не задействована магия JVM.

Ответ 3

Вышеприведенный ответ о Interning справедлив. Что-то нужно учитывать, если вы это сделаете:

Integer i3 = new Integer(10);
Integer i4 = new Integer(10);

У вас не будет новых объектов, так как вы создали новые объекты. Если вы напишете код следующим образом, он будет интернирован:

Integer i3 = Integer.valueOf(10);
Integer i4 = Integer.valueOf(10);

Теперь они снова будут тем же самым объектом. Если вы посмотрите на метод valueOf внутри класса Integer.java в файле src.zip, вы увидите, где он проверяет, не превышает ли значение int значение от -128 до 127, он вызывает новый класс Integer иначе он загружает его из кеша.

Ответ 4

Integer i1 = 1000;
Integer i2 = 1000;

Компилятор "блокирует" int 1000 как объект Integer. Для этого он преобразует источник в следующее:

Integer i1 = Integer.valueOf(1000);
Integer i2 = Integer.valueOf(1000);

Теперь valueOf может быть простым вызовом new Integer(1000), но при создании нового объекта Integer каждый раз, когда поле int вставляется в квадрат, будет стоить как время, так и пробел. Чтобы этого избежать, класс Integer хранит массив объектов Integer для ограниченного диапазона значений int.

if(value> maxRange || value< minRange){
     //not in pool return new Integer
     return new Integer(value);
}else{
     //return pooled Integer object
     //for the value, pool contains all Integer
     //values from minRange to maxRange
     return integerPool[value-minRange];
}

Скорость, полученная против потерянной памяти, может быть отрегулирована путем установки диапазона с помощью аргумента jvm при запуске программы (по умолчанию afaik -127 - 128).

Ответ 5

Когда оператор Java == используется для сравнения чего-либо, кроме примитивных типов, он проверяет ссылочное равенство; это применимо даже тогда, когда сравниваемые вещи являются обернутыми примитивами. Кроме того, метод valueOf и сгенерированный компилятором оператор autoboxing, как правило, могут произвольно возвращать новый объект, который не будет равным ссылке на любую другую ранее существующую ссылку или возвращать ссылку на существующий объект (который, конечно, быть ссылочным равным любой ранее существующей ссылке, идентифицирующей тот же объект). Реализации необходимы для поддержки "пула" экземпляров Integer для значений от -128 до 127, так что все вызовы Integer.valueOf на любом конкретном номере в этом диапазоне будут возвращать ссылки на один и тот же объект, но кроме этого реализация было бы свободно делать что-то вроде

static Integer [] intPool = new Integer[256];

public Integer valueOf(int n)
{
  int hash = (n*0x18675309) >>> 24;
  Integer instance = intPool[n];
  if (instance == null && instance.value != n)
  {
    instance = new Integer(n);
    intPool[hash] = instance ;
  }
  return instance;
}

Я особо не ожидаю, что реализации Java будут делать что-то подобное, поскольку во многих случаях отношение "кэш-атака" может быть около 0%, а дополнительное время, затрачиваемое на поиск экземпляров в кеше, будет потрачено впустую. Тем не менее, никогда не было никакой гарантии, что ссылка, возвращаемая instanceOf, не будет соответствовать некоторой предыдущей ссылке, возвращенной этим методом (даже если она не соответствует последней ссылке, возвращаемой этим методом, некоторые алгоритмы кэширования могут привести к ее возвращает более раннюю ссылку, особенно если пул разделяется несколькими потоками без блокировки. Отсутствие блокировки никогда не приведет к тому, что код вернет что-либо, кроме ссылки на целое число с правильным значением, но может вызвать непредсказуемые изменения, в которых возвращаемые ссылки сравните равные). Только ссылки на объекты Integer, созданные напрямую с использованием конструктора new Integer(n), гарантируют уникальность; код, который ожидает, что какая-либо ссылка, возвращаемая valueOf, не соответствует какой-либо ссылке, возвращаемой valueOf, не заметив, что она не соответствует, должна считаться нарушенной.

Ответ 6

Сравнение строк и целочисленное сравнение с использованием == и!= дает булевы результаты не так, как мы ожидаем. Будьте осторожны и убедитесь, что возможные неизвестные результаты не мешают производительности, надежности и точности вашего программного обеспечения.

Ответ 7

"==" всегда сравнивать расположение памяти или ссылки на объекты значений. equals всегда сравнивает значения. но равно также косвенно использует оператор "==" для сравнения значений. Integer использует Integer cache для хранения значений от -128 до +127.If == оператор используется для проверки любых значений от -128 до 127, тогда он возвращает true. если какое-либо значение между -128 и 127 как

Integer i1 = -128; 
Integer i2 = -128; 
System.out.println(i1 == i2); // returns true

кроме указанного выше диапазона, он возвращает false

Integer i1 = 1000;
Integer i2 = 1000;
System.out.println(i1 == i2); // returns false

Обратитесь к ссылке за дополнительной информацией