
- •ОГЛАВЛЕНИЕ
- •ВВЕДЕНИЕ
- •ГЛАВА 1. ПРИНЦИПЫ ООП. КЛАССЫ И ОБЪЕКТЫ
- •1.1 Основные принципы ООП
- •1.2 Достоинства ООП
- •1.3 Недостатки ООП
- •1.4 Классы и объекты
- •1.5 Члены класса
- •1.6 Модификаторы объявления класса
- •1.7 Пакеты
- •1.8 Понятие имени
- •1.9 Понятие модуля компиляции
- •1.10 Поля
- •1.11 Управление доступом
- •1.12 Создание объектов
- •1.13 Конструкторы
- •1.14 Блоки инициализации
- •1.15 Статическая инициализация
- •1.16 Методы
- •1.16.1 Модификаторы методов
- •1.16.2 Статические методы
- •1.16.3 Вызов метода
- •1.16.4 Выполнение метода и возврат из него
- •1.16.5 Параметры метода
- •1.16.6 Применение методов для управления доступом
- •1.16.7 Ключевое слово this
- •1.16.8 Перегруженные методы
- •1.16.9 Метод main
- •1.16.10 Методы native
- •ГЛАВА 2. ОСНОВЫ ЛЕКСИКИ
- •2.1 Комментарии
- •2.2 Служебные слова
- •2.3 Идентификаторы
- •2.4 Литералы
- •2.4.1 Целочисленные литералы
- •2.4.2 Литералы с плавающей точкой
- •2.4.3 Логические литералы
- •2.4.4 Символьные литералы
- •2.4.5 Строковые литералы
- •2.5 Операторы
- •2.6 Разделители
- •2.7 Переменные
- •2.8 Простые типы
- •2.8.1 Целочисленные типы
- •byte
- •short
- •long
- •2.8.2 Числовые типы с плавающей точкой
- •float
- •double
- •2.8.3 Приведение типа
- •2.8.4 Автоматическое преобразование типов в выражениях
- •2.8.5 Символьный тип
- •2.8.6 Логический тип
- •2.9 Массивы
- •2.9.1 Многомерные массивы
- •2.9.2 Инициализация массивов
- •2.10 Операторы
- •2.10.1 Арифметические операторы
- •Операторы арифметических действий
- •Оператор деления по модулю
- •Операторы арифметических действий с присваиванием
- •Целочисленная арифметика
- •Арифметика с плавающей запятой
- •2.10.2 Инкремент и декремент
- •2.10.3 Целочисленные битовые операторы
- •Операторы битовой арифметики
- •Оператор побитового сдвига влево
- •Операторы побитового сдвига вправо
- •Операторы битовой арифметики с присваиванием
- •2.10.4 Операторы сравнения
- •2.10.5 Логические операторы
- •2.10.6 Оператор проверки соответствия типа
- •2.10.7 Условный тернарный оператор
- •2.10.8 Приоритеты операторов
- •2.11 Управление выполнением метода
- •2.11.1 Завершение работы метода
- •2.11.2 Ветвление
- •2.11.3 Циклы
- •while
- •do-while
- •2.11.4 Прерывание блоков инструкций
- •2.11.5 Переход на следующий виток цикла
- •2.11.6 Блок переключателей
- •ГЛАВА 3. ИСКЛЮЧЕНИЯ
- •3.1 Общие сведения об исключениях
- •3.2 Инструкция throw
- •3.3 Предложения throws
- •3.4 Предложения throws и переопределение методов
- •3.5 Предложения throws и методы native
- •3.6 Блок try-catch-finally
- •ГЛАВА 4. НАСЛЕДОВАНИЕ
- •4.1 Расширенный класс. Конструкторы расширенных классов
- •4.2 Порядок выполнения конструкторов
- •4.3 Переопределение методов при наследовании
- •4.4 Сокрытие полей
- •4.5 Доступ к унаследованным членам класса
- •4.6 Возможность доступа и переопределение
- •4.7 Сокрытие статических членов
- •4.8 Служебное слово super
- •4.9 Совместимость и преобразование типов
- •4.9.1 Совместимость
- •4.9.2 Явное преобразование типов
- •4.10 Проверка типа
- •4.11 Завершённые методы и классы
- •4.12 Абстрактные методы и классы
- •4.13 Класс Object
- •4.13.1 Метод сравнения объектов
- •4.13.2 Метод вычисления хеш-кода
- •4.13.3 Метод клонирования объектов
- •4.13.4 Метод получения ссылки на описание класса
- •4.13.5 Метод завершения работы объекта
- •4.13.6 Метод получения строкового представления
- •ГЛАВА 5. ИНТЕРФЕЙСЫ
- •5.1 Пример простого интерфейса
- •5.2 Объявление интерфейса
- •5.3 Константы в интерфейсах
- •5.4 Методы в интерфейсах
- •5.5 Модификаторы в объявлениях интерфейсов
- •5.6 Расширение интерфейсов
- •5.7 Наследование и сокрытие констант
- •5.8 Наследование, переопределение и перегрузка методов
- •5.9 Пустые интерфейсы
- •5.10 Абстрактный класс или интерфейс?
- •СПИСОК СОКРАЩЕНИЙ
- •СПИСОК ЛИТЕРАТУРЫ
единицы. Эти операторы уникальны в том плане, что могут использоваться как в префиксной, так и в постфиксной форме. Пример 37 иллюстрирует использование этих операторов.
Пример 37. Префиксная и постфиксная формы инкремента и декремента class IncDec {
public static void main(String[] args) { int a = 1;
int b = 2; int c = ++b; int d = a++; c++;
System.out.println("a = " + a); System.out.println("b = " + b); System.out.println("c = " + c); System.out.println("d = " + d);
}
}
Обратите внимание на результат выполнения программы (он объясняет различие между постфиксной и префиксной формами):
a = 2 b = 3 c = 4 d = 1
2.10.3 Целочисленные битовые операторы
Для целых числовых типов данных определен дополнительный набор операторов, с помощью которых можно проверять и модифицировать состояние отдельных битов соответствующих значений. В таблице 11 перечислены такие операторы. Они позволяют работать с каждым битом как с самостоятельной величиной.
90
Таблица 11. Битовые операторы
Оператор |
Результат |
|
|
~ |
Побитовое унарное отрицание (NOT) |
& |
Побитовое И (AND) |
| |
Побитовое ИЛИ (OR) |
^ |
Побитовое исключающее ИЛИ (XOR) |
>> |
Сдвиг вправо с заполнением битом знака |
>>> |
Сдвиг вправо с заполнением нолями |
<< |
сдвиг влево |
&= |
Побитовое И (AND) с присваиванием |
|= |
Побитовое ИЛИ (OR) с присваиванием |
^= |
Побитовое исключающее ИЛИ (XOR) с присваиванием |
>>= |
Сдвиг вправо с присваиванием и заполнением битом знака |
>>>= |
Сдвиг вправо с присваиванием и заполнением нолями |
<<= |
Сдвиг влево с присваиванием |
Операторы битовой арифметики
В таблице 12 показано, как каждый из операторов битовой арифметики воздействует на возможные комбинации битов своих операндов. Пример 38 иллюстрирует использование этих операторов в программе на языке Java.
Таблица 12. Операторы битовой арифметики
a |
b |
a | b |
a & b |
a ^ b |
~a |
0 |
0 |
0 |
0 |
0 |
1 |
1 |
0 |
1 |
0 |
1 |
0 |
0 |
1 |
1 |
0 |
1 |
1 |
1 |
1 |
1 |
1 |
0 |
0 |
91
Пример 38. Операторы битовой арифметики class Bitlogic {
public static void main(String[] args) {
String binary[] = { "0000", "0001", "0010", |
|
"0011", |
"0100", "0101", |
"0110", |
"0111", "1000", |
"1001", |
"1010", "1011", |
"1100", |
"1101", "1110", |
|
"1111" }; |
||
int a = 3; |
// 0+2+1 |
или двоичное 0011 |
|
int b = 6; |
// 4+2+0 |
или |
двоичное 0110 |
int c = a | b; |
|
|
|
int d = a & b; |
|
|
|
int e = a ^ b; |
|
|
|
int f = (~a & b) | (a |
& ~b); |
||
int g = ~a & 0x0f; |
|
|
|
System.out.println("a |
= " + binary[a]); |
||
System.out.println("b |
= " + binary[b]); |
||
System.out.println("a |
| b = " + binary[c]); |
||
System.out.println("a |
& b = " + binary[d]); |
||
System.out.println("a |
^ b = " + binary[e]); |
System.out.println("~a & b | а & ~b = " + binary[f]);
System.out.println("~a = " + binary[g]);
}
}
Результат выполнения программы будет выглядеть следующим образом:
a = 0011 b = 0110
a | b = 0111 a & b = 0010 a ^ b = 0101
~a & b | a & ~b = 0101 ~а = 1100
92
Оператор побитового сдвига влево
Оператор << выполняет сдвиг влево всех битов своего левого операнда на число позиций, заданное правым операндом. При этом часть битов в левых разрядах выходит за границы и теряется, а соответствующие правые позиции заполняются нолями. Ранее уже говорилось об автоматическом повышении типа всего выражения до int в том случае, если в выражении присутствуют операнды типа int или целых типов меньшего размера. Если же хотя бы один из операндов в выражении имеет тип long, то и тип всего выражения повышается до long.
Операторы побитового сдвига вправо
Оператор >> означает в языке Java побитовый сдвиг вправо. Он перемещает все биты своего левого операнда вправо на число позиций, заданное правым операндом. Когда биты левого операнда выдвигаются за самую правую позицию слова, они теряются. При сдвиге вправо освобождающиеся старшие (левые) разряды сдвигаемого числа заполняются предыдущим содержимым знакового разряда. Такое поведение называют расширением знакового разряда, а сам оператор – оператором арифметического сдвига (он сохраняет смысл деления числа на 2 и для положительных, и для отрицательных чисел).
В программе в примере 34 байтовое значение преобразуется в строку, содержащую его шестнадцатеричное представление. Обратите внимание: сдвинутое значение приходится маскировать, то есть логически умножать на значение 0х0f, для того, чтобы очистить заполняемые в результате расширения знака биты и понизить значение до пределов, допустимых при индексировании массива шестнадцатеричных цифр.
93
Пример 39. Арифметический сдвиг вправо class HexByte {
public static void main(String[] args) { char hex[] = {'0', '1', '2', '3',
'4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};
byte b = (byte) 0xf1; System.out.println("b = 0x" +
hex[(b >> 4) & 0x0f] + hex[b & 0x0f]);
}
}
Результат работы программы будет следующим: b = 0xf1
Часто требуется, чтобы при сдвиге вправо расширение знакового разряда не происходило, а освобождающиеся левые разряды просто заполнялись бы нолями. Для этого используют т.н. оператор логического сдвига вправо >>> (см. пример 40).
Пример 40. Логический сдвиг вправо class ByteUShift {
public static void main(String[] args) { char hex[] = {'0', '1', '2', '3',
'4', '5', '6', '7', '8', '9', 'а', 'b', 'с', 'd', 'e','f'};
byte b = (byte) 0xf1; byte c = (byte) (b >> 4); byte d = (byte) (b >> 4);
byte e = (byte) ((b & 0xff) >> 4); System.out.println(" b = 0x" +
hex[(b >> 4) & 0x0f] + hex[b & 0x0f]); System.out.println(" b >> 4 = 0x" +
hex[(c >> 4) & 0x0f] + hex[c & 0x0f]); System.out.println("b >>> 4 = 0x" +
hex[(d >> 4) & 0x0f] + hex[d & 0x0f]); System.out.println("(b & 0xff) >> 4 = 0x" +
hex[(e >> 4) & 0x0f] + hex[e & 0x0f]);
}
}
94