Пару слов о Джаве

У ДиБРа увидел прекрасное. Как вы думаете, что выведет следующий код:

public class Main {
    public static void main(String[] args) {
        Integer a = 10, b = 10; 
        Integer c = 150, d = 150;
        System.out.println(a == b);
        System.out.println(c == d);
    }
}

Как ни странно, но «true» и «false». Насколько я понял по комментариям, это происходит из-за того, в Джаве экземпляры Integer (видимо для скорости) в диапазоне [-128; 127] предопределены. Поэтому объекты «a» и «b» равны (ссылаются на один объект), а «c» и «d» нет. А на равенство значений надо проверять вызовом метода «equals».

Поделиться
Отправить
19 комментариев
dinoel

Представляю сколько часов потрачено на поиски и исправления багов связаных с таким поведением ...

Svan

В связи с этим вспомнился, почему—то, недавний наезд на PHP...

Александр Бабаев (bealex.moikrug.ru)

Есть замечательная книжка, называется Java Puzzlers http://www.javapuzzlers.com​. Там сотня глав, попадается очень забавное.

Александр Бабаев (bealex.moikrug.ru)

Ну, и сама концепция, object interning, много где используется. :)

Евгений Степанищев (bolknote.ru)

Комментарий для bealex.moikrug.ru:

Процитируй что-нибудь :)

Александр Бабаев (bealex.moikrug.ru)

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

System.out.print(«H» + «a»);
System.out.print(’H’ + ’a’);
-​-​ 1.
System.out.println((int) (char) (byte) -1);
-​-​ 2.
int j = 0;
for (int i = 0; i < 100; i++)
  j = j++;

System.out.println(j);
-​-​ 3.
int i = 0;
while (i == i + 1) { }
-​-​

Это простые, там есть и с многопоточностью, с классами, со стандартной библиотекой... Не могу найти с тернарным оператором, там неявное приведение типов забавное.

Fulcrum (fulc.ru)

«как ни странно»

Евгений Степанищев (bolknote.ru)

Комментарий для bealex.moikrug.ru:

Интересно, конечно!

Евгений Степанищев (bolknote.ru)

Комментарий для fulc.ru:

Спасибо!

Александр Бабаев (bealex.moikrug.ru)

Лучше, конечно, книжку прочитать, часть из вещей общеполезна :) А тут примерно так:

  1. ’H’ + ’a’ — сложение двух чисел, «H» + «a» — сложение двух строк.
  2. (int) (char) (byte) -1 = 65535 что-ли, так как char — беззнаковый тип (единственный в Java), а остальные — со знаком.
  3. j = 0, особенность работы с постинкрементом и присваиванием (оно раскрывается в int tmp = j; j = j + 1; j = tmp;). Там еще куча с инкрементами есть, все не упомню :)
  4. вполне очевидно, что цикл быстро закончится. Но если правильно объявить i (не «int i = 0», а «double i = Double.POSITIVE_INFINITY»), то цикл превратится в бесконечный.
Eyeless

Ну дык объект и примитив разные вещи. Хочешь арифметику — пользуй примитивы, хочешь ООП — объекты. Мешаешь вместе — ССЗБ.

Евгений Степанищев (bolknote.ru)

Комментарий для Eyeless:

Вот «Пайтон» мне нравится тем, что там нет примитивов.

Илья Ермолов (twitter.com/iErmolov)

Комментарий для Евгения Степанищева:

Из секретных источников (на самом деле на JavaOne рассказали) стало известно, что в 9-й или 10-й джаве тоже не будет примитивов. Но вот это поведение вряд ли изменится в силу того, что у джавы должна быть обратная совместимость. Ещё есть кэш строковых констант, кстати.

Александр Бабаев (bealex.moikrug.ru)

Комментарий для Илья Ермолов (twitter.com/iErmolov):

Ну, интернирование статических строк есть вообще почти везде.

PastorGL

Это JAVAAAAAAA!!!111

А если серьёзно, то пару раз нарвавшись на подобные вещи, быстро привыкаешь смотреть в исходники стандартных пакетов. У санок-то оно ещё ничего, а в айбиэмовской жабе местами такие чудеса попадаются, что просто диву даёшься, как такое вообще ухитряется работать в mission critical appliances...

Евгений Степанищев (bolknote.ru)

Комментарий для PastorGL:

Ну, это не только в Джаве же такое есть. Например, у Пайтона тоже может оказаться, что ID двух разных (с точки зрения программиста) объектов — одно и то же. Но операция сравнения значений в языке — два равно, что всё-таки более интуитивно.

http://desh.su

Комментарий для Евгения Степанищева:

В CPython, кстати, тоже статически выделена память для маленьких чисел (у меня в 2.7 это диапазон [-5, 256]).
А в Jython подобный диапазон [-100, 899].

Работает подобный пример, только, естественно, с оператором «is» вместо «==».

В том же духе в CPython, например, переиспользуются строки, встречаемые в коде (имена классов, методов, переменных, ключевые слова, etc).

stafi

для сравнения объектов необходимо использовать метод equals, читайте букварь

Евгений Степанищев (bolknote.ru)

Комментарий для stafi:

Вы до конца-то мой пост прочитали? Или только букварь умеете читать?

Популярное