Почему делает Java неявно (без броска), преобразовывают 'длинное' в 'плавание'?

delete удалит свойство объекта, но не повторно индексирует массив или обновит его длину. Это делает, появляется, как будто это не определено:

> myArray = ['a', 'b', 'c', 'd']
  ["a", "b", "c", "d"]
> delete myArray[0]
  true
> myArray[0]
  undefined

Примечание, что это на самом деле не установлено на значение undefined, скорее свойство, удалено из массива, делание его кажется неопределенным. Chrome dev инструменты ясно дает понять это различие путем печати empty при входе массива.

> myArray[0]
  undefined
> myArray
  [empty, "b", "c", "d"]

myArray.splice(start, deleteCount) на самом деле удаляет элемент, повторно индексирует массив и изменяет его длину.

> myArray = ['a', 'b', 'c', 'd']
  ["a", "b", "c", "d"]
> myArray.splice(0, 2)
  ["a", "b"]
> myArray
  ["c", "d"]

36
задан Eric Wilson 18 August 2009 в 13:26
поделиться

3 ответа

Тот же вопрос можно задать для long в double - оба преобразования могут потерять информацию.

Раздел 5.1.2 языка Java В спецификации сказано:

Расширяющиеся примитивные преобразования не терять информацию об общем величина числового значения. Действительно, преобразования, расширяющиеся от целого тип к другому целочисленному типу не вообще потерять любую информацию; то числовое значение сохраняется точно. Расширение конверсий с плавающего на double в выражениях strictfp также точно сохранить числовое значение; однако такие преобразования, которые не strictfp может потерять информацию о общая величина преобразованных значение.

Преобразование целого или длинного значения. плавать или иметь длинное значение для двойной, может привести к потере точность - то есть результат может потерять некоторые из наименее значимых битов Значение. В этом случае полученный значение с плавающей запятой будет правильно округленная версия целочисленное значение, используя IEEE 754 режим округления до ближайшего (§4.2.4).

Другими словами, даже если вы можете потерять информацию, вы знаете, что значение будет по-прежнему находиться в общем диапазоне целевого типа.

Выбор, безусловно, мог бы быть были сделаны так, чтобы требовать, чтобы все неявные преобразования вообще не теряли информацию - поэтому int и long to float были бы явными и long ] to double было бы явно. ( int - double в порядке; double имеет достаточную точность для точного представления всех значений int .)

В некоторых случаях это было бы полезно - в некоторых случаях нет. Языковой дизайн - это компромисс; вы не можете победить их всех. Не знаю, какое бы решение я принял ...

43
ответ дан 27 November 2019 в 05:22
поделиться

Спецификация языка Java , Глава 5: Преобразование и продвижение решает эту проблему:

5.1.2 Расширяющееся примитивное преобразование

Следующие 19 конкретных преобразований на примитивных типах называются расширяющиеся примитивные преобразования:

  • байт в short, int, long, float или double
  • short в int, long, float или double
  • char в int, long, float или double
  • int в long, float или double
  • long to float или double
  • float to double

Расширяющиеся примитивные преобразования не теряют информацию об общей величине числового значения.

...

Преобразование int или long значение для float, или long значение для double, может привести к потере точности, то есть результат может потерять некоторые из наименее значимых битов значения. В этом случае результирующее значение с плавающей запятой будет правильно округленной версией целочисленного значения

Другими словами, JLS различает потерю величины и потерю точность . Например, от

int до байт - это (потенциальная) потеря величины, потому что вы не можете сохранить 500 в байте .

long to float - это потенциальная потеря точности, но не величины, потому что диапазон значений для float больше, чем для longs.

Итак, правило:

  • Потеря величины: требуется явное приведение ;
  • Потеря точности: приведение не требуется.

Незаметно? Конечно. Но я надеюсь, что это проясняет это.

  • Потеря точности: приведение не требуется.
  • Незаметно? Конечно. Но я надеюсь, что это проясняет это.

  • Потеря точности: приведение не требуется.
  • Незаметно? Конечно. Но я надеюсь, что это проясняет это.

    41
    ответ дан 27 November 2019 в 05:22
    поделиться

    Хотя вы правы, что long использует больше битов внутри, чем float, язык java работает по расширяющемуся пути:

    byte -> short -> int -> long -> float -> double

    Для преобразования слева направо (расширяющее преобразование) не требуется приведение (вот почему разрешено long to float). Для преобразования справа налево (сужающее преобразование) необходимо явное приведение.

    15
    ответ дан 27 November 2019 в 05:22
    поделиться
    Другие вопросы по тегам:

    Похожие вопросы: