значения оказались несовместимыми. Как следствие, выражение null всегда может быть успешно преобразовано к любому ссылочному типу. Но можно найти способ все-таки закодировать запрещенное преобразование.
Child c=new Child(); // Child2 c2=(Child2)c; // запрещенное преобразование Parent p=c; // расширение Child2 c2=(Child2)p; // сужение
Такой код будет успешно скомпилирован, однако, разумеется, при исполнении он всегда будет генерировать ошибку в последней строке. 'Обманывать' компилятор смысла нет.
Оператор конкатенации строк
Этот оператор уже рассматривался достаточно подробно. Если обоими его аргументами являются строки, то происходит обычная конкатенация. Если же тип String имеет лишь один из аргументов, то второй необходимо преобразовать в текст. Это единственная операция, при которой производится универсальное приведение любого значения к типу String.
Это одно из свойств, выделяющих класс String из общего ряда.
Правила преобразования уже были подробно описаны в этой лекции, а оператор конкатенации рассматривался в лекции 'Типы данных'.
Небольшой пример:
int i=1; double d=i/2.; String s='text'; print('i='+i+', d='+d+', s='+s');
Результатом будет:
i=1, d=0.5, s=text
Числовое расширение
Наконец, последний вид преобразований применяется при числовых операциях, когда требуется привести аргумент(ы) к типу длиной в 32 или 64 бита для проведения вычислений. Таким образом, при числовом расширении осуществляется только расширение примитивных типов.
Различают унарное и бинарное числовое расширение.
Унарное числовое расширение
Это преобразование расширяет примитивные типы byte, short или char до типов int по правилам расширения примитивных типов.
Унарное числовое расширение может выполняться при следующих операциях:
унарные операции + и - ;
битовое отрицание ~ ;
операции битового сдвига <<, >>, >>>.
Операторы сдвига имеют два аргумента, но они расширяются независимо друг от друга, поэтому данное преобразование является унарным. Таким образом, результат выражения 5<<3L имеет тип int. Вообще, результат операторов сдвига всегда имеет тип int или long.
Примеры работы всех этих операторов с учетом расширения подробно рассматривались в предыдущих лекциях.
Бинарное числовое расширение
Это преобразование расширяет все примитивные числовые типы, кроме double, до типов int, long, float, double по правилам расширения примитивных типов. Бинарное числовое расширение происходит при числовых операторах, имеющих два аргумента, по следующим правилам:
если любой из аргументов имеет тип double, то и второй приводится к double ;
иначе, если любой из аргументов имеет тип float, то и второй приводится к float ;
иначе, если любой из аргументов имеет тип long, то и второй приводится к long ;
иначе оба аргумента приводятся к int.
Бинарное числовое расширение может выполняться при следующих операциях:
арифметические операции +, -, *,
операции сравнения <, <=, >, >=, ==, != ;
битовые операции &, |, ^ ;
в некоторых случаях для операции с условием ?:.
Примеры работы всех этих операторов с учетом расширения подробно рассматривались в предыдущих лекциях.
Тип переменной и тип ее значения
Теперь, когда были подробно рассмотрены все примеры преобразований, нужно вернуться к вопросу переменной и ее значений.
Как уже говорилось, переменная определяется тремя базовыми характеристиками: имя, тип, значение. Имя дается произвольным образом и никак не сказывается на свойствах переменной. А вот значение всегда имеет некоторый тип, не обязательно совпадающий с типом самой переменной. Поэтому необходимо рассмотреть все возможные типы переменных и выяснить, значения каких типов они могут иметь.
Начнем с переменных примитивных типов. Поскольку эти переменные действительно