Отправляет email-рассылки с помощью сервиса Sendsay
  Все выпуски  

Java Programer&Developer. Выпуск 4 - Операторы и присвоения 1


Выпуск 4 - Операторы и присвоения (часть 1)

Здравствуйте, дорогие читатели!

Ответы на тест в предыдущем выпуске

  1. Ответ В: разность между количеством отрицательных чисел и количеством положительных чисел равна единице (отрицательных чисел больше).

  2. Ответ A, В, C, D, E: все идентификаторы допустимы.

  3. Ответ В, D: все варианты являются допустимыми сигнатурами методов. Но для того, чтобы быть точкой входа в приложение, метод main() должен быть public static void и принимать один параметр типа String[].

  4. Ответ D: порядок Декларация пакета, импорты, классы должен быть соблюдён строго.

  5. Ответ A, E: массив из 25-ти элемнтов индексируется от 0 до 24. Все элементы инициализируются нулём.

  6. Ответ D: объект типа Holder создаётся в третьей строчке. Ссылка на этот объект передаётся в метод bump() в пятой строчке. И внутри метода поле held объекта изменяет значение с 100 на 101.

  7. Ответ C: в метод decrement() передаётся копия аргумента d; копия увеличивает значение на единицу, но сам аргумент нет.

  8. Ответ A: сборщик мусора не может быть вызван принудительно. На вызовы System.gc() и Runtime.gc() нельзя полагаться на 100%, потому что сборка мусора может быть отсрочена в пользу потока более высокой приоритетности. Поэтому ответы B и D неверны. Ответ C неверен хотя бы потому, что метод gc() не принимает никаких аргументов. Ответ E просто напросто декларирует, что объект может быть собран сборщиком мусора, когда тот начнёт свою работу.

  9. Ответ D: 16-тибитный тип short вартируется от -215 до 215-1 согласно Java спецификации вне зависимости от платформы.

  10. Ответ D: 8-мибитный тип byte вартируется от -27 до 27-1 согласно Java спецификации вне зависимости от платформы.


Операторы и присвоения" (Operators and assignments)

Операторы в Java используются для разнообразных операций (всех необходимых). Все Java операторы перечислены в Таблице 2.1:

Таблица 2.1: Операторы Java в нисходящем порядке приоритетности массива

КатегорияОператоры
 
Унарные++    --    +    -    !    ~    ()
Арифметические*    /    %
 +    -
Сдвиг<<    >>    >>>
Сравнение<    <=    >    >=    instanceof
 ==    !=
Поразрядные&    ^    |
Быстрого принятия решения&&    ||
Условные?:
Присвоение=    op=
 

2.1. Порядок вычисления

В Java, в отличие от многих других языков, явный порядок вычисления зафиксирован. Результат любого выражения считается слева направо. Рассмотрим фрагмент кода:

1. int [] a = { 4, 4 };
2. int b = 1;
3. a[b] = b = 0;

Какой элемент массива модифицирован? Какое значение b использовано для выбора элемента массива: 0 или 1? Согласно правилу вычисления слева направо самое левое выражение a[b] должно быть вычислено первым. Так что это a[1]. Затем вычисляется b, то есть активируется ссылка на переменную b. Затем вычисляется константа 0, что не требует никаких операций. Затем в вычисление включаются операторы. Вычисление при этом проводится в порядке приоритетности и ассоциацивности. Для присвоений ассоциативность - справа налево. Таким образом, сначала значение 0 присваивается переменной b, которая, в свою очередь, затем присваивается последнему элементу массива a.

Рекомендуется использовать простые выражения и скобки, чтобы улучшить читаемость кода. Код, сгенерированый компилятром, будет тем же самым, несмотря на скобки.

2.2. Унарные операторы

Большинство оперторов имеют два операнда. Например, когда мы производим умножение, то делаем это с двумя числами. Однако, унарные операторы применяются только к одному операнду. В Java представлены семь унарных операторов:

  • Инкремент (увеличение значения на 1) и декремент (уменьшение значения на 1): ++ и --
  • Унарный плюс и минус: + и -
  • Поразрядное инвертирование: ~
  • Логическое дополнение: !
  • Приведение типа: ( )

Строго говоря, приведение типа - это не оператор. Но мы его обсуждаем именно в таком ключе, потому что к нему применяются все тезисы нашего дальнейшего обсуждения.

Инкремент (увеличение значения на 1) и декремент (уменьшение значения на 1): ++ и --

Эти операторы изменяют значение выражения добавлением или вычитанием 1. Например, если переменная x типа int равна 10, то ++x (--x) равно 11 (соответственно, 9). Результат записывается в x.

В предыдущих примерах операторы находились перед переменной. Они могут находиться и после неё. И ++x, и x++ дают один и тот же результат, сохраняемый в x. Но значение всего выражения отличается. Например, если y = x++, то значение y равно исходному значению x. Если же y = ++x, то значение y на единицу больше, чем исходное значение x. В обоих случаях значение x увеличивается на 1.

Если инкремент (декремент) расположен слева от выражения, то выражение модифицируется перед тем (после того), как оно начинает участвовать в остальном вычислении. Это называется пре-инкремент (пре-декремент). Соответсвенно, если оператор находится справа от выражения, то в остальном вычислении участвует исходное значение этого выражения. И инкремент (декремент) происходит после того, как вычисление всего выражения завершено.

Таблица 2.2. показывает значения x и y после применения инкремента и декремента справа и слева.

Таблица 2.2: Примеры премодификации и постмодификации инкрементом и декрементом

КатегорияОператоры
 
Начальное значение xВыражениеИтоговое значение yИтоговое значение x
5y = x++56
5y = ++x66
5y = x--54
5y = --x44
 

Унарный плюс и минус: + и -

Унарные операторы + и - отличаются от обычных бинарных операторов + и -, которые трактуются, как сложение и вычитание. Унарный + не имеет никакого эфекта, кроме подчёркивания положительной природы численного литерала. Унарный - отрицает выражение (было положительным - стало отрицательным, было отрицательным - стало положительным). Примеры:

1. x = -3;
2. y = +3;
3. z = -(y + 6);

В примере единственное обоснование использования унарного плюса - подчёркивание, что переменной y присваивается положительное число. Общее выравнивание кода также более красиво с эстетической точки зрения :). Заметим, что в третьей строке унарный оператор применяется не к литералу, а к выражению. Таким образом, значение переменной z присваивается -9.

Поразрядное инвертирование: ~

Каждый примитивный тип Java представляется в виртуальной машине так, что представление не зависит от платформы. Это означает, что битовый шаблон, используемый для представления некоего отдельного числа, будет всегда тем же самым. Таким образом и манипулирование битами - процесс более эффективный, в силу независимости от платформы. Поразрядное инвертирование означает, что в двоичном представлении числа 0 заменяется на 1, а 1 - на 0.

Например, применение этого оператора к байту с содержимым 00001111 даст 11110000.

Логическое дополнение: !

Оператор ! инвертирует логическое значение выражения. Например, !true = false. Этот оператор часто используется в тестовой части if () конструкции. Эффект этого - изменение значения логического выражения. То есть обработчики if () и else могут быть легко обменяться местами. Рассмотрим два эквивалентных фрагмента кода:

1. public Object myMethod(Object x) {
2.     if (x instanceof String) {
3.     // do nothing
4.     }
5.     else {
6.         x = x.toString();
7.     }
8.     return x;
9. }

и

1. public Object myMethod(Object x) {
2.     if (!(x instanceof String)) {
3.         x = x.toString();
4.     }
5.     return x;
6. }

В первом фрагменте, тестирование происходит в строке 2, но присвоение - в строке 6, если тест не пройдёт. Это сделано немного громоздко при помощи ветви else конструкции if/else. Второй фрагмент использует оператор логического дополнения, поэтому во второй строке тест инвертирован и может быть прочтён как Если x не строка. Если тест проходит, то обработка происходит в третьей строке и никакого отдельного else не требуется и результирующий код более краток и более читаем.

Приведение типа: ( )

Приведение типа используется для явной конвертации выражения в заданный тип. Операция возможна только для допустимых типов. И во время компиляции, и во время выполнения программы, приведение типа проверяется на корректность. И этот аспект будет описан в дальнейших выпусках рассылки.

Приведение типа применяется для изменения типа значений примитивного типа. Например, мы можем форсировать конвертацию double к int как, например, в следующем фрагменте:

int circum = (int)(Math.PI * diameter);

Здесь приведение типа выражается фрагментом (int). Если бы этот фрагмент отсутсвовал, то компилятор бы выдал ошибку, поскольку double значение, возвращаемое арифметическим выражением не может быть точно представлено int значением, к которому присваивается. Присвоение типа - это способ, которым программист говорит компилятору: "Я знаю, что такое присвоение может быть рискованным, но верь мне, ведь я - специалист". Конечно, если результат при этом теряет точность так, что программа не функционирует должным образом, - это ответсвенность программиста.

Присвоение типа может быть применено и к объектным (непримитивным) типам. Это типично, например, для случаев, когда используются контейнеры типа Vector. Если вы помещаете объект типа String в Vector, то когда вы его извлекаете, тип, возвращаемый методом elementAt(), будет Object. Для использования извлечённого объекта как String нужно применить приведение типа, как, например, в следующем фрагменте кода:

1. Vector v = new Vector();
2. v.add ("Hello");
3. String s = (String)v.get(0);

В данном примере приведение типа имеет место в третьей строке (конструкция (String)). И хотя компилятор допускает такое приведение типа, во время выполнения программы всё равно проверяется, является объект извлечённый из Vector на самом деле объектом типа String. В будущих выпусках рассылки я расскажу о допустимых приведениях типов.


Дорогие читатели! Если у вас возникают вопросы по тексту рассылки, я с удовольствием на них отвечу. Мой почтовый адрес идёт последней строкой в данном выпуске (at означает @). Кроме того, присылайте мне интересующие вас темы, которые я могла бы осветить в рассылке, делитесь опытом или просто комментируйте. Я также буду рада и благодарна вам, если вы проголосуете за этот выпуск. Форма голосования находится внизу выпуска.

Всего доброго,
Наталия Македа
natalia.macheda at gmail.com


В избранное