2016-08-24 3 views
0

Почему эта программа печатает false в первом заявлении печати и истинно в заявлении печати.? i и i1 - это два разных объекта, поэтому первый оператор должен печатать «истина», как и ожидалось, но второй оператор печати печатает «ложь», что создает путаницу.Сравнение двух классов Integer Wrapper

public static void main(String[] args) { 
     Integer i = new Integer(10); 
     Integer i1 = new Integer(10); 
     System.out.println(i == i1); //printing false 
     i++; 
     i1++; 
     System.out.println(i == i1);//printing true 
    } 
+0

Возможный дубликат [Как правильно сравнить два типа Integer в Java? ] (http://stackoverflow.com/questions/1514910/how-to-properly-compare-two-integers-in-java) – ArcticLord

+0

@ Ишан Вы можете проверить формулировку вопроса? Вы говорите: «Первый оператор должен печатать« истина », как и ожидалось», но в листинге показан первый оператор, который печатает false (аналогично для второго оператора печати). –

ответ

5

Использование new ключевое слово всегда создает два разных экземпляра. Таким образом, всегда верно следующее:

new Integer(10) != new Integer(10) 

отсюда первая строка печати «ложь».

Тогда:

i++; 

скрывает распаковка и бокс. Это эквивалентно:

i = Integer.valueOf(i.intValue() + 1); 

Как описано в the Javadoc of Integer.valueOf, значение от -128 до 127 (по крайней мере) кэшируются: вы получаете обратно кэшированный экземпляр Integer.valueOf(11) как для i++ и i1++, отсюда и вторая линия печать "правда".

+0

Интересно. Когда вы делаете то же самое с +500, он на самом деле действительно выводит false во второй раз https://ideone.com/yvSSFS – baao

+0

@baao, это не обязательно, на самом деле это происходит только на ideone. ["Этот метод всегда будет кэшировать значения в диапазоне от -128 до 127 включительно и может кэшировать другие значения за пределами этого диапазона."] (Https://docs.oracle.com/javase/7/docs/api/java /lang/Integer.html#valueOf (int)) Очевидно, что 501 не кэшируется JVM, запущенным в настоящее время ideone. –

+0

Хорошо, это имеет смысл. Спасибо за объяснение! – baao

1

Здесь:

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

вы запрашиваете динамически размещаемые два экземпляра Integer типа класса, это даст вам две разные ссылки. Если вы измените его на:

Integer i = 10; 
Integer i1 = 10; 

затем ссылку на I и i1 будет равен, так как при малых значениях классов обертки использовать кэшированные объекты.

Это:

i++; 
    i1++; 

объясняется: 15.14.2. Postfix Increment Operator ++ в JLS (курсив мой):

Перед добавлением, бинарное числовое расширение (§5.6.2) выполняется на значение 1 и значение переменной. При необходимости сумма сужается сужением примитивной конверсии (§5.1.3) * и/или подвергнутой конверсии бокса (§5.1.7) типу переменной перед ее сохранением.

также примечание ниже важно где сказано, что перед применением оператора распаковка преобразования может произойти следующее:

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

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

0

Сначала это сравнение ссылок, следовательно, получение значения false, а во втором - сравнение значений (при приращении он не привязан к примитивному int и, следовательно, увеличивается на 11 и автоматически заправляется, то же для i1). второй вызов (11 == 11), следовательно, истина.

-1

Класс Integer имеет столько же классов, что и метод equals. Вы можете легко сравнить два экземпляра Integer, как это:

Integer int1 = new Integer(2); 
Integer int2 = new Integer(2); 
if(int2.equals(int1)) { 
    // true 
} 

Рассмотрим реализацию метода Equals во всех ваших собственных сущностей/DTOS:

class Car { 
    private String color; 
    private Integer model; 

    public Car(String color, Integer model) { 
    this.color = color; 
    this.model = model; 
    } 

    public String getColor() { return color; } 
    public Integer getModel() { return model; } 

    @Override 
    public boolean equals(final Object obj) { 
    if(this == obj) { 
     return true; // You are actually comparing the same instances 
    } 
    if(obj instanceof Car) { // Now you know both obj are instances of class Car 
     final Car other = (Car) obj; // Safe to cast 
     return Objects.equal(color, other.getColor()) 
     && Objects.equal(model, other.getModel() 
     ; 
    } 
    return false; 
    } 
} 
Смежные вопросы