В данном примере переменной absval присваивается значение переменной val, если это значение больше или равно нулю. А если значение переменной val отрицательное, то переменной absval присваивается значение val со знаком “минус”, что в итоге дает положительную величину. Код, выполняющий ту же самую функцию, но с помощью логической конструкции if-else, будет выглядеть следующим образом: if(val < 0) absval = -val; else absval = val;
Рассмотрим еще один пример применения оператора ?. В этом примере программы выполняется деление двух чисел, но не допускается деление на нуль: // Предотвращение деления на нуль с помощью оператора ?. class NoZeroDiv { public static void main(String args[]) { int result; for(int i = -5; i < 6; i++) { // Деление на нуль предотвращается. result = i != 0 ? 100 / i : 0; if(i != 0) System.out.println("100 / " + i + " is " + result); } } }
Ниже приведен результат выполнения данной программы. 100 / -5 is -20 100 / -4 is -25 100 / -3 is -33 100 / -2 is -50 100 / -1 is -100 100 / 1 is 100 100 / 2 is 50 100 / 3 is 33 100 / 4 is 25 100 / 5 is 20
Обратите особое внимание на следующую строку кода: result = i != 0 ? 100 / i : 0;
где переменной result присваивается результат деления числа 100 на значение переменной i. Но деление выполняется только в том случае, если значение переменной i не равно нулю. В противном случае переменной result присваивается нулевое значение.
Значение, возвращаемое оператором ?, не обязательно присваивать переменной. Его можно, например, использовать в качестве параметра при вызове метода. Если же все три выражения оператора ? имеют тип boolean, то сам оператор ? может быть использован в качестве условия для выполнения цикла или оператора if. Ниже приведена немного видоизмененная версия предыдущего примера программы. Ее выполнение дает такой же результат, как и прежде. // Предотвращение деления на нуль с помощью оператора ?. class NoZeroDiv2 { public static void main(String args[]) { for(int i = -5; i < 6; i++) if(i != 0 ? true : false) System.out.println("100 / " + i + " is " + 100 / i); } }
Обратите внимание на выражение, определяющее условие выполнения оператора if. Если значение переменной i равно нулю, то оператор ? возвращает логическое значение false, что предотвращает деление на нуль, и результат не отображается. В противном случае осуществляется обычное деление. Упражнение для самопроверки по материалу главы 5
Покажите два способа объявления одномерного массива, состоящего из 12 элементов типа double.
Покажите, как инициализировать одномерный массив целочисленными значениями от 1 до 5.
Напишите программу, в которой массив используется для нахождения среднего арифметического десяти значений типа double. Используйте любые десять чисел.
Измените программу, написанную в примере для опробования 5.1, таким образом, чтобы она сортировала массив символьных строк. Продемонстрируйте ее работоспособность.
В чем отличие методов indexOf () и lastlndexOf () из класса String?
Все символьные строки являются объектами типа String. Покажите, как вызываются методы length () и charAt () для строкового литерала "I like Java" (Мне нравится Java).
Расширьте класс Encode таким образом, чтобы в качестве ключа шифрования использовалась строка из восьми символов.
Можно ли применять поразрядные операторы к значениям типа double?
Перепишите приведенную ниже последовательность операторов, воспользовавшись оператором ?.if (х < 0) у = 10; else у = 20;
В приведенном ниже фрагменте кода содержится знак &. Какой оператор он обозначает: поразрядный или логический? Обоснуйте свой ответ.boolean а, Ь; // ... if (а & Ь) ...
Является ли ошибкой превышение верхней границы массива? Является ли ошибкой использование отрицательных значений для доступа к элементам массива?
Как обозначается оператор сдвига вправо без знака?
Перепишите рассмотренный ранее в этой главе класс MinMax таким образом, чтобы в нем использовалась разновидность for-each цикла for.
В примере для опробования 5.1 была реализована пузырьковая сортировка. Можно ли в программе из этого примера заменить обычный цикл for его разновидностью for-each? Если нельзя, то почему?
Можно ли управлять оператором switch с помощью объектов типа String?
Глава 6 Дополнительные сведения о методах и классах
Основные навыки и понятия
Управление доступом к членам классов
Передача объектов при вызове методов
Возврат объектов из методов
Перегрузка методов
Перегрузка конструкторов
Применение рекурсии
Использование ключевого слова static
Применение внутренних классов
Использование аргументов переменной длины
В этой главе возобновляется рассмотрение классов и методов. Сначала будет показано, каким образом контролируется доступ к членам класса, а затем рассмотрены особенности передачи и возврата объектов из методов, перегрузки методов, использования рекурсии и ключевого слова static. Кроме того, в этой главе будут представлены вложенные классы и методы с аргументами переменной длины. Управление доступом к членам класса
Поддержка свойства инкапсуляции в классе дает два главных преимущества. Во-первых, класс связывает данные с кодом. Это преимущество использовалось в предыдущих примерах программ, начиная с главы 4. И во-вторых, класс предоставляет средства для управления доступом к его членам. Именно эта, вторая преимущественная особенность и будет рассмотрена ниже.
В языке Java, по существу, имеются два типа членов класса: открытые (public) и закрытые (private), хотя в действительности дело обстоит немного сложнее. Доступ к открытому члену свободно осуществляется из кода, определенного за пределами класса. Именно этот тип члена класса использовался в рассматривавшихся до сих пор примерах программ. А закрытый член класса доступен только методам, определенным в самом классе. С помощью закрытых членов и организуется управление доступом.
Ограничение доступа к членам класса является основополагающей частью объектно-ориентированного программирования, поскольку оно позволяет исключить неверное использование объекта. Разрешая доступ к закрытым данным только с помощью строго определенного ряда методов, можно предупредить присваивание неверных значений этим данным, выполняя, например, проверку диапазона представления чисел. Для закрытого члена класса нельзя задать значение непосредственно в коде за пределами класса. Но в то же время можно полностью управлять тем, как и когда данные используются в объекте. Следовательно, правильно реализованный класс образует некий “черный ящик”, которым можно пользоваться, но внутренний механизм «его действия закрыт для вмешательства извне.
В рассмотренных ранее примерах программ не уделялось никакого внимания управлению доступом, поскольку в Java члены класса по умолчанию доступны из остальных частей программы. (Иными словами, они открыты для доступа по умолчанию.) Это удобно для создания небольших программ (в том числе и тех, что служат примерами в данной книге), но недопустимо в большинстве реальных условий эксплуатации программного обеспечения. Ниже будет показано, какими языковыми средствами Java можно пользоваться для управления доступом. Модификаторы доступа в Java
Управление доступом к членам класса в Java осуществляется с помощью трех модификаторов доступа (называемых также спецификаторами): public, private и protected. Если модификатор не указан, то принимается тип доступа по умолчанию. В этой главе будут рассмотрены модификаторы public и private. Модификатор protected непосредственно связан с наследованием, и поэтому он будет обсуждаться в главе 8.
Когда член класса обозначается модификатором public, он становится доступным из любого другого кода в программе, включая и методы, определенные в других классах. Когда же член класса обозначается модификатором private, он может быть доступен только другим членам этого класса. Следовательно, методы из других классов не имеют доступа к закрытому члену данного класса.