Операторы и операции

Вопрос 1

Какое число выведет в консоль следующий код?

int a = 1;

int sum = a + (a = 2);

System.out.println(sum);

а. 4
б. 3
в. Код не скомпилируется
г. Возникнет ошибка времени выполнения

б. 3

В строке int sum = a + (a = 2); машине необходимо выполнить операцию сложения. Вычисление операндов для операции сложения (как впрочем и других арифметических операций) всегда происходит слева направо, даже если правый операнд заключён в скобки.

Таким образом сперва будет разыменована переменная а перед знаком "+", и левый операнд будет считаться равным единице. Затем машина начнёт вычислять второй операнд сложения. Для этого она, действительно, войдёт в скобки, выполнит присваивание и вернёт два. Правый операнд сложения будет равным два.

Таким образом в результате переменной sum будет присвоено 3.

Вопрос 2

Какое число выведет в консоль следующий код?

int a = -2;

int b = -a;

System.out.println(a);

а. 2
б. -2
в. Код не скомпилируется
г. Возникнет ошибка времени выполнения

б. -2

В строке int b = -a; значение переменной а никак не меняется. Переменная а разыменовывается, результатом разыменовывания станет -2. Унарный оператор минус "-" будет применён к этому значению и поменяет его на 2 (без минуса). Положительная двойка будет присвоена переменной b. Ни в одном месте значение переменной a не поменяется и оно так и останется -2.

Вопрос 3

Какое число выведет в консоль следующий код?

int a = -2;

int b = +a;

System.out.println(b);

а. 2
б. -2
в. Код не скомпилируется
г. Возникнет ошибка времени выполнения

б. -2

В строке int b = +a; унарный оператор "+" не даст никакого эффекта. Унарный плюс может использоваться для разупаковывания объектов в примитивы с автоматическим продвижением к int, или только для продвижения "узких" примитивов (byte, short, char) к int. Подробности в спецификации. Но знак величины с отрицательного на положительный унарный плюс не поменяет.

Вопрос 4

Что выведет в консоль следующий код?

Integer i = null;

Integer j = 0;


if (j > i) {

System.out.println("0 > null");

}

а. 0 > null
б. Код не скомпилируется
в. Возникнет ошибка времени выполнения

в. Возникнет ошибка времени выполнения

Сравнение j > i выбросит java.lang.NullPointerException. Все операторы сравнения (<,>,<=,>=,==) выбрасывают NPE, если один из операндов во время выполнения программы оказывается null. Это связано с тем, что перед сравнением происходит автораспаковка объектного типа в примитивный. В нашем случае Integer в int. Распаковка null'а невозможна и порождает исключительную ситуацию.

Вопрос 5

Что выведет в консоль следующий код?

Integer a = 0;

Integer b = 0;


System.out.println(a == b);

а. true
б. false

а. true

Оператор ==, применённый к переменным ссылочного типа, возвращает true, если обе переменные указывают на один и тот же объект. У типа Integer есть особенность: аналогично String'ам Java поддерживает для этого типа пул значений от 0 до 127. Таким образом, в данном случае обе переменные и a, и b указывают на один и тот объект в пуле, а значит сравнение с помощью == вернёт true.

Вопрос 6

Что будет, если откомпилировать и запустить следующий код (в Java 10)?

var x = 1;

x += 0.5;

System.out.println(x);

а. Код не откомпилируется.
б. Код откомпилируется, но во время выполнения вылетит исключение.
в. Код откомпилируется и выведет на консоль 1.
г. Код откомпилируется и выведет на консоль 1.5.

в. Код откомпилируется и выведет на консоль 1.

var x = 1;

Ключевое слово var можно использовать только в том случае, если тип переменной можно вывести из контекста инструкции, содержащей var. Собственно в данном контексте переменной x присваивается значение литерала 1. Целочисленные литералы по умолчанию имеют тип int, значит переменная var x будет определена как int.

x += 0.5;

Данная строка развернётся в x = (int) (x + 0.5) в соответствии с правилами развёртывание составных операторов присваивания. При этом приведение будет проведено к типу переменной, в нашем случае, как мы уже выяснили, это int.

Очевидно, что поскольку int не может содержать дробной части, то в итоге дробная часть будет усечена и значение переменной будет равно 1. Это число и будет выведено на экран.

Вопрос 7

Что будет, если откомпилировать и запустить следующий код:

System.out.println('0' + 0);

а. Код не откомпилируется.
б. Код откомпилируется, но во время выполнения вылетит исключение.
в. Программа отработает нормально и выведет в консоль 0.
г. Программа отработает нормально и выведет в консоль 00.
д. Программа отработает нормально и выведет в консоль 48.

д. Программа отработает нормально и выведет в консоль 48.

Левый операнд '0' имеет тип char будет интерпретироваться либо как число, либо как символ, в зависимости от типа правого операнда. В нашем случае, правый операнд 0 -- это целочисленный литерал, имеющий тип int. Значит левый операнд сложения будет интерпретирован именно как число, а не символ.

Числовое значение '0' равно 48. 48 + 0 = 48. Поэтому на консоль будет выведено именно это число.

Вопрос 8

Что будет, если откомпилировать и запустить следующий код:

System.out.println('0' + '0');

а. Программа выведет на экран 00.
б. Программа выведет на экран 96.

б. Программа выведет на экран 96.

Если один из операндов сложения является строкой (String), то второй операнд, будет интерпретирован как строка. Но в данном примере оба варианта имеют тип char. Тип char не похож в этом отношении на строки. Если литерал или переменная типа char участвует в арифметическом выражении, то оно просто интерпретируется как число.

Символу '0' соответствует число 48 (его code point), а значит сумма двух символов '0' -- это сумма 48 + 48 = 96.

Вопрос 9

Что будет, откомпилировать и запустить следующий код:

System.out.println(null != null);

а. Код не откомпилируется.
б. Код откомпилируется, но во время выполнения вылетит исключение.
в. Программа отработает нормально и выведет в консоль true.
г. Программа отработает нормально и выведет в консоль false.

г. Программа отработает нормально и выведет в консоль false.

Переменная любого ссылочного типа может быть сравнена с null и сам null вполне можно сравнивать с самим собой на предмет равенства-неравенства (но не больше-меньше).

И в Java, и в других языках программирования встречаются сущности, которые оказываются не равными самим себе. К null в Java это не относится. Он равен самому себе, поэтому сравнение null != null - ложно.

Вопрос 10

Что будет, откомпилировать и запустить следующий код:

System.out.println(.0/.0);

а. Код не откомпилируется.
б. Код откомпилируется, но во время выполнения вылетит исключение.
в. Программа отработает нормально и выведет в консоль Infinity.
г. Программа отработает нормально и выведет в консоль NaN.

г. Программа отработает нормально и выведет в консоль NaN.

Если числовой литерал начинается с точки, то он интерпретируется как число типа double со значение ноль целых и сколько-то десятых (сотых и т.д.). Например, .0 интерпретируется как 0.1 (то есть ноль целых одна десятая).

В выражении .0/.0, таким образом, оба операнда относятся к типу double и оба равны нулю.

Деление на ноль операндов типа double в Java не приводит к возникновению исключительной ситуации, а возвращает одно из трёх значений: либо Infinity, либо -Infinity, либо NaN. Если оба операнда оказываются равными нулю, то возвращается именно NaN.