Анализатор обнаружил использование класса BigDecimal, которое может вести себя не так, как ожидал разработчик.
Анализатор выдает предупреждения в следующих ситуациях:
1. Вызов конструктора, аргументом которого является число с плавающей точкой.
Пример такого использования:
BigDecimal bigDecimal = new BigDecimal(0.6);
Про использование таким образом конструктора есть несколько примечаний в документации класса.
Если не вдаваться в подробности, то созданный таким образом объект будет иметь значение 0.59999999999999997779553950749686919152736663818359375 вместо 0,6. Это связано с невозможностью точного представления числа с плавающей точкой.
А ведь BigDecimal прежде всего необходим для вычислений с крайне высокими требованиями к точности. И примеру, есть ПО, в котором от точности вычислений может зависеть человеческая жизнь (ПО для самолетов, ракет или для медицинского оборудования). Поэтому погрешность даже в 30 разряде после запятой может сыграть свою роль.
Чтобы этого избежать, необходимо создавать объект BigDecimal одним из следующих способов:
BigDecimal bigDecimal1 = BigDecimal.valueOf(0.6);
BigDecimal bigDecimal2 = new BigDecimal("0.6");
2. Вызов метода 'equals', так как вполне вероятно имелся ввиду метод 'compareTo'.
Принято считать, что для сравнения объектов нужно вызывать метод 'equals'. Тут не поспорить!
И когда разработчик работает с объектом этого класса, то может считать, что он просто работает с объектом, который может содержать очень большое вещественное число. И вызывая метод 'equals', подразумевает эквивалентность сравниваемых чисел.
В таком случае, следующий фрагмент кода может удивить разработчика:
BigDecimal bigDecimal1 = BigDecimal.valueOf(0.6);
BigDecimal bigDecimal2 = BigDecimal.valueOf(0.60);
....
if (bigDecimal1.equals(bigDecimal2)) // false
{
// code
}
Нюанс кроется в том, что при сравнении через метод 'equals' сравнивается не только значение, но и количество значащих чисел после запятой. Как раз этого разработчик может и не ожидать. Чтобы сравнивать числа без учета значащих чисел после запятой необходимо использовать метод 'compareTo':
BigDecimal bigDecimal1 = BigDecimal.valueOf(0.6);
BigDecimal bigDecimal2 = BigDecimal.valueOf(0.60);
....
if (bigDecimal1.compareTo(bigDecimal2) == 0) // true
{
// code
}
Данная диагностика классифицируется как:
|