2015-12-16 4 views
4

Мне интересно, что это внутреннее поведение Java для следующего фрагмента кода:Примитивное и объекты сравнения с оператором ==

Long a = 123L; 
long b = 123; 
System.out.println("a equals b?: " + (a == b)); 

В результате true хотя сравнение два Long объектов будет false (потому что он сравнивает их ссылки). Это преобразование Java Long в его примитивное значение, потому что обнаруживает оператор == против другого примитивного объекта?

+4

«хотя сравнение двух длинных объектов было бы ложным из-за того, что оно сравнивает их ссылку» - в этом случае, даже если он помещен в коробку, это было бы верно из-за кеширования объектов в штучной упаковке для небольших чисел. –

ответ

5

Это Java преобразование Long объекта в его примитивное значение, поскольку детектирует == оператора против другого примитивного объекта?

Да. Один из операндов является примитивным типом, а другой операнд конвертируется в примитив путем распаковки.

JLS section 15.21.1 говорит (курсив мой):

Если операнды операции равенства являются оба числового типа, или один имеет числовой тип, а другой является обратимым (§5.1.8) в числовой тип, двоичное числовое продвижение выполняется в операндах (§5.6.2).

Обратите внимание, что бинарное числовое продвижение выполняет преобразование значений (§5.1.13) и может выполнять преобразование для распаковки (§5.1.8).

Также важно отметить, что эталонное равенство выполняется только в том случае, если оба операнда являются объектами. JLS section 15.21.3 говорит:

Если операнды оператора равенства являются либо ссылочным, либо нулевым, то операция является равенством объекта.

2

От the Java Tutorials:

Autoboxing и распаковка

Autoboxing является автоматическим преобразованием, что компилятор Java делает между примитивными типами и их классами соответствующего объекта оберткой . Например, преобразование int в Integer, double в Double и т. Д. Если преобразование идет другим путем, это называется unboxing.

Вот простейший пример Autoboxing:

Character ch = 'a'; 

Остальные примеры в этом разделе использование генериков. Если вы не , но знакомы с синтаксисом дженериков, см. Уроки 0: .

Рассмотрим следующий код:

List<Integer> li = new ArrayList<>(); 
for (int i = 1; i < 50; i += 2) 
    li.add(i); 

Хотя вы сложите значения INT в качестве примитивных типов, а не объектов Integer, к ли, код компилируется. Поскольку li - это список объектов Integer, а не список значений int, вы можете задаться вопросом, почему компилятор Java не выдает ошибку времени компиляции. Компилятор не генерирует ошибку, потому что он создает объект Integer из i и добавляет объект в li. Таким образом, компилятор преобразует предыдущий код в во время выполнения следующий:

List<Integer> li = new ArrayList<>(); 
for (int i = 1; i < 50; i += 2) 
    li.add(Integer.valueOf(i)); 

Конвертирование элементарного значения (в Int, например) в качестве объекта соответствующего класс-оболочки (целого число) называется Autoboxing. Java-компилятор применяет Autoboxing, когда примитив значение:

  • передается в качестве параметра метода, который ожидает объект в соответствующего класса-оболочки.
  • Назначается переменной класса оболочки . Рассмотрите следующий метод:

    public static int sumEven (List li) { int sum = 0; for (Integer i: li) if (i% 2 == 0) sum + = i; возвратная сумма; }

Поскольку остаток (%) и унарный плюс (+ =) операторы не применяются к объектам Integer, вы можете задаться вопросом, почему компилятор Java компилирует метод без выдачи каких-либо ошибок. Компилятор не генерирует ошибку, потому что он вызывает метод intValue для преобразования целого числа в Int во время выполнения:

public static int sumEven(List<Integer> li) { 
    int sum = 0; 
    for (Integer i : li) 
     if (i.intValue() % 2 == 0) 
      sum += i.intValue(); 
     return sum; 
} 

Преобразования объекта типа обертки (целое число) в соответствующем примитивного (INT) значение называется распаковкой. Компилятор Java применяется распаковки, когда объект класса обертки:

  • передается в качестве параметра метода, ожидающего значение соответствующего примитивного типа.
  • Назначается переменной соответствующего примитивного типа.
Смежные вопросы