Эккель Брюс
Шрифт:
Конечно, здесь можно было бы использовать стандартную конструкцию if-else (описываемую чуть позже), но тернарный оператор гораздо компактнее. Хотя С (где этот оператор впервые появился) претендует на звание лаконичного языка, и тернарный оператор вводился отчасти для достижения этой цели, будьте благоразумны и не используйте его всюду и постоянно — он может ухудшить читаемость программы.
Операторы + и += для String
В Java существует особый случай использования оператора: операторы + и += могут применяться для конкатенации (объединения) строк, и вы уже это видели. Такое действие для этих операторов выглядит вполне естественно, хотя оно и не соответствует традиционным принципам их использования.
При создании С++ в язык была добавлена возможность перегрузки операторов, позволяющей программистам С++ изменять и расширять смысл почти любого оператора. К сожалению, перегрузка операторов, в сочетании с некоторыми ограничениями С++, создала немало проблем при проектировании классов. Хотя реализацию перегрузки операторов в Java можно было осуществить проще, чем в С++ (это доказывает язык С#, где существует простой механиз перегрузки), эту возможность все же посчитали излишне сложной, и поэтому программистам на Java не дано реализовать свои собственные перегруженные операторы, как это делают программисты на С++.
Использование + и += для строк (String) имеет интересные особенности. Если выражение начинается строкой, то все последующие операнды также должны быть строками (помните, что компилятор превращает символы в кавычках в объект String).
int х = 0. у = 1. z = 2;
String s = "х. у, z
System.out.println(s + x + у + z),
В данном случае компилятор Java приводит переменные х, у и z к их строковому представлению, вместо того чтобы сначала арифметически сложить их. А если вы запишете
System.out.println(x + s); то и здесь Java преобразует х в строку.
Типичные ошибки при использовании операторов
Многие программисты склонны второпях записывать выражение без скобок, даже когда они не уверены в последовательности вычисления выражения. Это верно и для Java.
Еще одна распространенная ошибка в С и С++ выглядит следующим образом:
while(x = у) { // .
}
Программист хотел выполнить сравнение (==), а не присвоение. В С и С++ результат этого выражения всегда будет истинным, если только у не окажется нулем; вероятно, возникнет бесконечный цикл. В языке Java результат такого выражения не будет являться логическим типом (boolean), а компилятор ожидает в этом выражении именно boolean и не разрешает использовать целочисленный тип int, поэтому вовремя сообщит вам об ошибке времени компиляции, упредив проблему еще перед запуском программы. Поэтому подобная ошибка в Java никогда не происходит. (Программа откомпилируется только в одном случае: если х и у одновременно являются типами boolean, и тогда выражение х = у будет допустимо, что может привести к ошибке.)
Похожая проблема возникает в С и С++ при использовании поразрядных операторов И и ИЛИ вместо их логических аналогов. Поразрядные И и ИЛИ записываются одним символом (& и |), в то время как логические И и ИЛИ требуют в написании двух символов (&& и ||). Так же, как и в случае с операторами = и ==, легко ошибиться и набрать один символ вместо двух. В Java компилятор предотвращает такие ошибки, так как он не позволяет использовать тип данных в неподходящем контексте.
Операторы приведения
Слово приведение используется в смысле «приведение к другому типу». В определенных ситуациях Java самостоятельно преобразует данные к другим типам. Например, если вещественной переменной присваивается целое значение, компилятор автоматически выполняет соответствующее преобразование (int преобразуется во float). Приведение позволяет сделать замену типа более очевидной или выполнить ее принудительно в случаях, где это не происходит в обычном порядке.
Чтобы выполнить приведение явно, запишите необходимый тип данных (включая все модификаторы) в круглых скобках слева от преобразуемого значения. Пример:
//: operators/Casting.java
public class Casting {
public static void main(String[] args) { int i = 200; long lng = (long)i;
Ing = i; // "Расширение", явное преобразование не обязательно long lng2 = (long)200; lng2 = 200;
// "Сужающее" преобразование i = (int)lng2; // Преобразование необходимо
}
} ///:-
Как видите, приведение может выполняться и для чисел, и для переменных. Впрочем, в указанных примерах приведение является излишним, поскольку компилятор при необходимости автоматически преобразует целое int к типу long. Однако это не мешает вам выполнять необязательные приведения — например, чтобы подчеркнуть какое-то обстоятельство или просто для того, чтобы сделать программу более понятной. В других ситуациях приведение может быть необходимо для нормальной компиляции программы.
В С и С++ приведение могло стать источником ошибок и неоднозначности. В Java приведение безопасно, за одним исключением: при выполнении так называемого сужающего приведения (то есть от типа данных, способного хранить больше информации, к менее содержательному типу данных), то есть при опасности потери данных. В таком случае компилятор заставляет вас выполнить явное приведение; фактически он говорит: «это может быть опасно, но, если вы уверены в своей правоте, опишите действие явно». В случае с расширяющим приведением явное описание не понадобится, так как новый тип данных способен хранить больше информации, чем прежний, и поэтому потеря данных исключена.