Почему (i <= j && j <= i && i! = J) оценивается как ИСТИНА?

104

Я написал фрагмент кода Java, который работает в бесконечном цикле.

Ниже приведен код:

public class TestProgram {
    public static void main(String[] args){
        Integer i = new Integer(0);
        Integer j = new Integer(0);

        while(i<=j && j<=i && i!=j){
            System.out.println(i);
        }
    }
}

В приведенном выше коде, видя условие в whileцикле, сначала кажется, что эта программа не войдет внутрь whileцикла. Но на самом деле это бесконечный цикл, и он продолжает выводить значение.

Что здесь происходит?

Кшитидж Джайн
источник
8
Простой ответ: i<=j && j<=i && i!=jэто условие всегда истинно. Просто возьмите листок бумаги и оцените, вы его поймаете :)
Pradeep Simha
4
То, как вы создаете целое число, неверно. Используйте 'compareTo'
nachokk
7
Если вы никогда не измените iили j, когда вы ожидаете, что цикл завершится?
Фред Ларсон,
33
@PradeepSimha Для простых значений int это всегда будет давать false . Из i<=jи j<=iможно заключить, что i == j, что противоречит последним слагаемым. Таким образом, все выражение оценивается как ложное, и время не вводится. Ключевым моментом здесь является идентичность объекта!
Sirko
4
Кстати, это головоломка 32 из книги «Головоломки Java: ловушки, подводные камни и угловые случаи».
Cyanfish

Ответы:

188
  • i <= jоценивается в true, так как авто распаковка происходит за ИНТ сравнений , а затем , как iи jудерживать значение по умолчанию 0.

  • j <= iоценивается по trueуказанной выше причине.

  • i != jоценивается как true, потому что оба iи jявляются разными объектами. А при сравнении объектов нет необходимости в автоматической распаковке.

Все условия верны, и вы не меняетесь iи jв цикле, поэтому он работает бесконечно.

Джунед Ахсан
источник
10
не могли бы вы объяснить, почему! = проверяет индекс памяти ссылочных объектов, а <= проверяет неупакованное значение Integer ?? .. почему существует такая разница между этими операторами?
Пунит Радж
41
Операторы @PunithRaj <&> работают с примитивами, а не с объектами, поэтому для этих операторов происходит автоматическая распаковка. Но операторы == и! = Также могут использоваться для сравнения объектов, поэтому здесь нет необходимости распаковывать, поэтому объекты сравниваются.
Juned Ahsan
14
Ах, скрытые опасности неявного бокса / распаковки !!
Hot Licks
3
Stack Overflow нужно просто добавить новый тег: «Автоматическая распаковка была самой большой ошибкой, когда-либо сделанной в Java». :-). За исключением авторов книг по Java Puzzler. Используйте его, чтобы отмечать подобные вопросы.
user949300
4
обратите внимание, что Integer.valueOf(0) == Integer.valueOf(0)всегда оценивается как истина, потому что в этом случае возвращается тот же объект (см. IntegerCache grepcode.com/file/repository.grepcode.com/java/root/jdk/openjdk/… )
Виталий Федоренко
40

Потому что вы сравниваете

  • 0 < = 0 (true) // unboxing

  • 0 > = 0 (true) // unboxing

  • reference != secondReference (true)поскольку вы создаете объекты, а не примитивное сравнение. Итак, это оценивается как while(true) { // Never ending loop }.

Ашвани
источник
2
Ой! скрытый Дракон авто РАСПАКОВКА ... Хорошее объяснение.
HybrisHelp 08
17

Целочисленные объекты разные. Он отличается от базового типа int.

См. Этот ответ: Как правильно сравнить два целых числа в Java?

i != jЧасть правды, что вы ожидали ложные.

Полковник Паник
источник
Хотя это правда, здесь это не имеет значения и не дает ответа на вопрос.
Кон,
6
@Kon: На самом деле это ответ. Условия №1 и №2 оцениваются trueкак «автобокс». В случае №3 автобоксинг не применяется, и сравнение происходит на уровне объекта (области памяти).
домой
1

Цикл не заканчивается, потому что ваше условие истинно (i! = J истинно, потому что есть 2 разных объекта, используйте вместо этого Integer.valueOf), а внутри цикла значения не меняются, поэтому ваше условие остается истинным навсегда.

Сильвиу Бурча
источник
1

Целочисленные объекты разные. Он отличается от базового типа int. так что вы можете просто так делать. что вы делаете, вы просто сравниваете объект и, конечно же, результат верный.

Кричевской
источник
1

Есть два разных случая, которые мы должны сначала понять,

Случай 1:

        Integer i = new Integer(10);
        Integer j = new Integer(10);

        System.out.println((i<=j && j<=i && i!=j));
        System.out.println(i!=j);

случай 2:

        Integer i = 10;
        Integer j = 10;

        System.out.println((i<=j && j<=i && i==j));
        System.out.println(i==j);

оба разные, так как

в случае 1: i!=jбудет trueпотому, что оба ссылаются на два разных объекта в куче и не могут быть одинаковыми. Но

в случае 2: i==jбудет trueпотому, что оба 10 являются целочисленными литералами, а Java поддерживает pool for Integer literalsзначение (-128 <= X <= 127). Итак, в этом случае 10 <= 127 результатов истинны, поэтому оба будут ссылаться на один и тот же объект.

Ахилеш Дхар Дубей
источник
0

Возможно, причина в том, что и i, и j являются объектами, а сравнение объектов - это не то же самое, что сравнение ссылок на объекты. Пожалуйста, подумайте об использовании! Iequals (j) вместо i! = J

Эрик Гопак
источник
0

Программа продолжает отображать одно и то же значение, iпотому что вы не увеличиваете или не уменьшаете значение iили j. Условие в for всегда оценивается как истинное, так что это бесконечный цикл.

user28646
источник
Я думаю, что вопрос был больше о той i!=jчасти, которая на удивление соответствует истине, а не о <=сравнениях.
Soravux
0

Целое число a = новое целое число (0); Целое число b = новое целое число (0);

При сравнении <= и> = будет использоваться значение 0 без упаковки, а при сравнении! = Ссылки будут выполнены успешно, поскольку они являются разными объектами.

Даже это тоже будет работать i, e

Целое число a = 1000; Целое число b = 1000;

но это не так:

Целое число a = 100; Целое число b = 100;

Причина в том, что Integer внутренне использует кеширование для объектов Integer от -128 до 127 и возвращает экземпляры из этого кеша для охваченного диапазона. Я не уверен, но думаю, что вы также можете изменить его максимальное значение в пакете "java.lang.Integer.IntegerCache.high".

Для лучшего понимания проверьте URL: https://www.owasp.org/index.php/Java_gotchas#Immutable_Objects_.2F_Wrapper_Class_Caching

Вахид
источник
-3

вы должны знать, что это немного отличается в && this и this &, когда вы используете &&, тогда, когда первое условие истинно, тогда он проверяет второе условие, если оно ложно, тогда оно не проверяет третье условие, потому что в операторе &, если одно условие ложно, все утверждение ложно, если используется || тогда, если он видит true, он возвращает true в вашем коде, потому что i и j равны, первое и второе условие истинно, тогда в третьем условии оно будет ложным, потому что они равны, а условие - false.

Сара Содагари
источник
Я не знаю, почему мой ответ получает значение мин, потому что мой ответ верен, см. эту ссылку, ее истинность, затем, прежде чем получать мины на мой ответ, прочитайте больше stackoverflow.com/questions/5564410/difference-between-and
sara Sodagari