Философия Java | страница 71
В С и С++ приведение могло стать источником ошибок и неоднозначности. В Java приведение безопасно, за одним исключением: при выполнении так называемого сужающего приведения (то есть от типа данных, способного хранить больше информации, к менее содержательному типу данных), то есть при опасности потери данных. В таком случае компилятор заставляет вас выполнить явное приведение; фактически он говорит: «это может быть опасно, но, если вы уверены в своей правоте, опишите действие явно». В случае с расширяющим приведением явное описание не понадобится, так как новый тип данных способен хранить больше информации, чем прежний, и поэтому потеря данных исключена.
В Java разрешается приводить любой простейший тип данных к любому другому простейшему типу, но это не относится к типу boolean, который вообще не подлежит приведению. Классы также не поддерживают произвольное приведение. Чтобы преобразовать один класс в другой, требуются специальные методы. (Как будет показано позднее, объекты можно преобразовывать в рамках семейства типов; объект Дуб можно преобразовать в Дерево и наоборот, но не к постороннему типу вроде Камня.)
Округление и усечение
При выполнении сужающих преобразований необходимо обращать внимание на усечение и округление данных. Например, как должен действовать компилятор Java при преобразовании вещественного числа в целое? Скажем, если значение 29,7 приводится к типу int, что получится — 29 или 30? Ответ на этот вопрос может дать следующий пример:
//: operators/CastingNumbers.java // Что происходит при приведении типов // float или double к целочисленным значениям? import static net.mindview.util.Print *;
public class CastingNumbers {
public static void main(String[] args) { double above = 0.7, below = 0.4; float fabove = 0.7f, fbelow = 0 4f; print("(int)above: " + (int)above); print("(int)below: " + (int)below), printC(int)fabove- " + (int)fabove); print("(int)fbelow. " + (int)fbelow),
}
} /* Output: (int)above: 0 (int)below. 0 (int)fabove: 0 (int)fbelow: 0 *///:-
Отсюда и ответ на наш вопрос — приведение от типов с повышенной точностью double и float к целочисленным значениям всегда осуществляется с усечением целой части. Если вы предпочитаете, чтобы результат округлялся, используйте метод round() из java.lang.Math. Так как этот метод является частью java.lang, дополнительное импортирование не потребуется.
Повышение
Вы можете обнаружить, что при проведении любых математических и поразрядных операций примитивные типы данных, меньшие int (то есть char, byte и short), приводятся к типу int перед проведением операций, и получаемый результат имеет тип int. Поэтому, если вам снова понадобится присвоить его меньшему типу, придется использовать приведение. (И тогда возможна потеря информации.) В основном самый емкий тип данных, присутствующий в выражении, и определяет величину результата этого выражения; так, при перемножении float и double результатом станет double, а при сложении long и int вы получите в результате long.