2016-03-17 8 views
2

Рассмотрим следующий пример:Понимание Double Autoboxing

public static void main(String[] args) { 
    double x1 = 0.0, y1 = -0.0; 
    Double a1 = x1, b1 = y1; 
    System.out.println(x1 == y1);  //1, true 
    System.out.println(a1.equals(b1)); //2, false 

    double x2 = 0.0, y2 = 0.0; 
    Double a2 = x2, b2 = y2; 
    System.out.println(x2 == y2);  //3, true 
    System.out.println(a2.equals(b2)); //4, true 

    double x3 = 0.0/0.0, y3 = 0.0/0.0; 
    Double a3 = x3, b3 = y3; 
    System.out.println(x3 != y3);  //5, true 
    System.out.println(!a3.equals(b3)); //6, false 
} 

Я пытался понять Autoboxing для Double, но не смог. Почему //2 печатает false, но //4 печатает true тогда как оба //1 и //3 отпечатки true. Почему они автообновлены по-другому?

Консалтинг следующего JLS 5.1.7 раздела я понял, что это не specicified:

Если р является значением типа двойного, то:

  • Если р не NaN, преобразование бокса преобразует р в ссылочную позицию r класс и тип Double, так что r.doubleValue() вычисляется как p

  • В противном случае конверсия бокса преобразуется p в опорном г класса и типа двойной таким образом, что r.isNaN() вычисляется в истинный

Так, являются //2, //4 и //6 в неустановленном получал метод поведения и, возможно, в конечном итоге в разных результатах в зависимости от реализация?

+2

http://docs.oracle.com/javase/8/docs/api/java/lang/Double.html#equals-java.lang.Object- ответ на ваш точный вопрос. – ajb

ответ

3

Все JAVA числовые типы знаковые, если не указано иначе

Таким образом, 0,0 представлено в двоичной системе, как 0000000 ........ 0000000

-0.0 представлен как 10000000 .... .... 0000000

Теперь, исходя из того, что я понимаю, при использовании equals() сравнение не выполняется по-разному из двух мест памяти, поэтому в вашем случае это терпит неудачу.

из пакета java.lang.Double

Double.equals(Double) реализуется следующим образом

public boolean equals(Object obj) { 
    return (obj instanceof Double) 
      && (doubleToLongBits(((Double)obj).value) == 
        doubleToLongBits(value)); 
} 
+0

Истина для бит-за-бит, за исключением того, что значения NaN * «сворачиваются до одного« канонического »значения NaN» *. См. Javadoc из ['Double.equals (Object obj)'] (https://docs.oracle.com/javase/7/docs/api/java/lang/Double.html#equals%28java.lang.Object%29) и ['Double.doubleToLongBits (двойное значение)'] (https://docs.oracle.com/javase/7/docs/api/java/lang/Double.html#doubleToLongBits%28double%29). – Andreas

+0

Добавлена ​​внутренняя реализация метода Double.equals (Double) 'из исходного пакета Java. –

+0

Вы уверены, что -0.0 представлен как 1000 .... 000? Потому что я думаю, что это -2^31 – ferit

3

Двойной равен метод документирована в API documentation. Операция double == документируется в Java Language Specification.

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

Double == совместим с арифметикой IEEE 754, в которой NaN не равно ни на что, даже самому себе, но 0.0 и -0.0 равны.

Двойной призван иметь метод equals, совместимый с его compareTo, отражающий общий порядок, и с его hashCode, поэтому хеш-таблицы будут работать с двойными клавишами. NaN считается равным самому себе, а -0,0 меньше, чем равным 0,0.

2

Если вы читали Javadoc для Double внимательно, вы заметите, что отрицательное и положительное ноль не эквивалентны, по крайней мере в сравнении с использованием equals():

От Javadoc:

Обратите внимание, что в большинстве случаи, в течение двух экземпляров класса Double, d1 и d2, значение d1.equals (d2) истинно тогда и только тогда, когда

d1.doubleValue() == d2.doubleValue() 

также имеет значение true. Однако есть два исключения:

Если d1 и d2 оба представляют Double.NaN, то метод equals возвращает true, хотя Double.NaN == Double.NaN имеет значение false. Если d1 представляет +0.0, тогда как d2 представляет -0.0, или наоборот, равный тест имеет значение false, хотя значение +0.0 == - 0.0 имеет значение true.

2

... для двух экземпляров класса Double, d1 и d2, значение d1.equals (d2) истинно тогда и только тогда, когда

d1.doubleValue() == d2.doubleValue() 

также имеет значение правда. Однако есть два исключения:

Если d1 и d2 оба представляют Double.NaN, то метод equals возвращает true, хотя Double.NaN == Double.NaN имеет значение false.

Если d1 представляет собой +0.0, тогда как d2 представляет -0.0, или наоборот, равный тест имеет значение false, хотя значение +0.0 == - 0.0 имеет значение true.

Это определение позволяет корректно работать с таблицами хэшей.

Пожалуйста, обратитесь: https://docs.oracle.com/javase/7/docs/api/java/lang/Double.html

1

Javadoc из Double.equals(Object obj):

Обратите внимание, что в большинстве случаев для двух экземпляров класса Double, d1 и d2, значение d1.equals(d2) является true, если и только если

d1.doubleValue() == d2.doubleValue() 

также имеет значение true. Тем не менее, есть два исключения:

  • Если d1 и d2 оба представляют собой Double.NaN, то метод возвращает equalstrue, даже если Double.NaN==Double.NaN имеет значение false.
  • Если d1 представляет +0.0d2, а представляет -0.0, или наоборот, тест equal имеет значение false, даже если +0.0==-0.0 имеет значение true.

Это определение позволяет работать с таблицами хеша.