Объяснение
При сравнении Integer
против int
с ==
необходимо преобразовать Integer
в int
. Это называется распаковка .
См. JLS§5.1.8 :
Если r
является ссылкой типа Integer
, то преобразование без распаковки преобразует r
в r.intValue()
В этот момент вы сравниваете int
с int
. А у примитивов нет понятия экземпляров, все они ссылаются на одинаковое значение . Таким образом, результат true
.
То есть фактический код, который у вас есть,
a.intValue() == c
приводит к сравнению 10 == 10
, оба значения int
, больше нет Integer
экземпляров.
Вы можете видеть, что new Integer(...)
действительно создает новые экземпляры, когда вы сравниваете Integer
против Integer
. Вы сделали это в a == b
.
Примечание
Конструктор new Integer(...)
устарел . Вместо этого вы должны использовать Integer#valueOf
, он потенциально быстрее и также использует внутренний кеш. Из документации :
Возвращает экземпляр Integer
, представляющий указанное значение int
. Если новый экземпляр Integer не требуется, этот метод обычно следует использовать в предпочтении перед конструктором Integer(int)
, поскольку этот метод может дать значительно лучшее пространство и время производительность кеширование часто запрашиваемые значения. Этот метод всегда будет кэшировать значения в диапазоне от -128
до 127
включительно, а может кэшировать другие значения вне этого диапазона.
Кэширование важно отметить здесь, так как оно дает ==
снова значение true (для кэшированных значений):
Integer first = Integer.valueOf(10);
Integer second = Integer.valueOf(10);
System.out.println(first == second); // true
Кэширование гарантировано для значений от -128
до +127
, но может использоваться и для других.
Также обратите внимание, что ваш b
фактически выходит из кеша, так как
Integer b = 10;
// same as
Integer b = Integer.valueOf(10);
// and not
Integer b = new Integer(10);
Итак бокс проходит через Integer
кеш (см. JLS§5.1.7 ).