К. Арнольд, Д. Гослинг - Язык программирования Java (1160779), страница 5
Текст из файла (страница 5)
Статический метод, модифицирующий поля объектов, — примерно то же самое, чтои фабрика из нашего примера, которая пытается изменить серийный номер давно проданного плеера.1.8. МассивыПростые переменные, содержащие всего одно значение, полезны, но для многих приложений их недостаточно. Скажем, для разработкипрограммы игры в карты требуется множество объектов Card, с которыми можно было бы оперировать как с единым целым.
Для таких случаев вязыке Java предусмотрены массивы.Массивом называется набор переменных, относящихся к одному типу. Доступ к элементам массива осуществляется посредством простыхцелочисленных индексов. В карточной игре объект Deck (колода) может выглядеть так:class Deck {final int DECK_SIZE = 52;Card[] cards = new Card[DECK_SIZE];}public void print() {for (int i = 0; i < cards.length; i++)System.out.println(cards[i]);}Сначала мы объявляем константу с именем DECK_SIZE, содержащую количество кард в колоде.
Затем поле cards объявляется в виде массива типаCard — для этого после имени типа в объявлении необходимо поставить квадратные скобки [ и ]. Размер массива определяется при его созданиии не может быть изменен в будущем.Вызов метода print показывает, как производится доступ к элементам массива: индекс нужного элемента заключается в квадратные скобки [ и ],следующие за именем массива.Как нетрудно догадаться по тексту программы, в объекте-массиве имеется поле length, в котором хранится количество элементов в массиве.Границами массива являются целые числа 0 и length-1. Если попытаться обратиться к элементу массива, индекс которого выходит за эти пределы,то возбуждается исключение IndexOutOfBounds.В этом примере также демонстрируется новый механизм объявления переменных — переменная цикла объявлена в секции инициализациицикла for.
Объявление переменной в секции инициализации — удобный и наглядный способ объявления простой переменной цикла. Такаяконструкция допускается лишь при инициализации цикла for; вы не сможете объявить переменную при проверке условия в операторе if илиwhile.Переменная цикла i существует лишь внутри оператора for. Переменная цикла, объявленная подобным образом, исчезает сразу же после егозавершения — это означает, что ее имя может использоваться в качестве имени переменной в последующих операторах цикла.Упражнение 1.8Измените приложение Fibonacci так, чтобы найденные числа Фибоначчи сохранялись в массиве и выводились в виде списка значений в концепрограммы.Упражнение 1.9Измените приложение Fibonacci так, чтобы числа Фибоначчи сохранялись в массиве.
Для этого создайте новый класс для хранения самого числаи логического значения, являющегося признаком четности, после чего создайте массив для ссылок на объекты этого класса.1.9. Строковые объектыДля работы с последовательностями символов в Java предусмотрены тип объектов String и языковая поддержка при их инициализации.
КлассString предоставляет разнообразные методы для работы с объектами String.Примеры литералов типа String уже встречались нам в примерах — в частности, в программе HelloWorld. Когда в программе появляетсяоператор следующего вида:System.out.println(“Hello, world”);компилятор Java на самом деле создает объект String, присваивает ему значение указанного литерала и передает его в качестве параметраметоду println.Объекты типа String отличаются от массивов тем, что при их создании не нужно указывать размер.
Создание нового объекта String и егоинициализация выполняются всего одним оператором, как показывает следующий пример:class StringDemo {static public void main(String args[]) {String myName = “Petronius”;}}myName = myName + “ Arbiter”;System.out.println(“Name = ” + myName);Мы создаем объект String с именем myName и инициализируем его строковым литералом. Выражение с оператором конкатенации +, следующееза инициализацией, создает новый объект String с новым значением. Наконец, значение myName выводится в стандартный выходной поток.Результат работы приведенной выше программы будет таким:Name = Petronius ArbiterКроме знака +, в качестве оператора конкатенации можно использовать оператор += как сокращенную форму, в которой название переменнойразмещается в левой части оператора.
Усовершенствованная версия приведенного выше примера выглядит так:class BetterStringDemo {static public void main(String args[]) {String myName = “Petronius”;String occupation = “Reorganization Specialist”;}}myName = myName + “ Arbiter”;myName += “ ”;myName += “(” + occupation + “)”;System.out.println(“Name = ” + myName);Теперь при запуске программы будет выведена следующая строка:Name = Petronius Arbiter (Reorganization Specialist)Объекты String содержат метод length, который возвращает количество символов в строке. Символы имеют индексы от 0 до length()-1.Объекты String являются неизменяемыми, или доступными только для чтения; содержимое объекта String никогда не меняется.
Когда впрограмме встречаются операторы следующего вида:str = “redwood”;// ... сделать что-нибудь со str ...str = “oak”;второй оператор присваивания задает новое значение ссылки на объект, а не содержимого строки. При каждом выполнении операции, котораяна первый взгляд изменяет содержимое объекта (например, использование выше +=), на самом деле возникает новый объект String, такжедоступный только для чтения, — тогда как содержимое исходного объекта String остается неизменным. Класс StringBuffer позволяет создаватьстроки с изменяющимся содержимым; этот класс описывается в главе 8, в которой подробно рассматривается и класс String.Самый простой способ сравнить два объекта String и выяснить, совпадает ли их содержимое, заключается в использовании метода equals:if (oneStr.equals(twoStr))foundDuplicate(oneStr, twoStr);Другие методы, в которых сравниваются части строки или игнорируется регистр символов, также рассматриваются в главе 8.Упражнение 1.10Измените приложение StringsDemo так, чтобы в нем использовались разные строки.Упражнение 1.11Измените приложение ImprovedFibonacci так, чтобы создаваемые в нем объекты String сначала сохранялись в массиве, а не выводились бы сразуже на печать методом println.1.10.
Расширение классаОдним из самых больших достоинств объектно-ориентированного программирования является возможность такого расширения, или созданияподкласса, существующего класса, при котором можно использовать код, написанный для исходного класса.При расширении класса на его основе создается новый класс, наследующий все поля и методы расширяемого класса. Исходный класс, длякоторого проводилось расширение, называется суперклассом.Если подкласс не переопределяет (override) поведение суперкласса, то он наследует все свойства суперкласса, поскольку, как уже говорилось,расширенный класс наследует поля и методы суперкласса.Примером с плеерами Walkman можно воспользоваться и здесь.
В последних моделях плееров устанавливаются два разъема для наушников,чтобы одну и ту же кассету могли слушать сразу двое. В объектно-ориентированном мире модель с двумя разъемами расширяет базовую модель.Эта модель наследует все характеристики и поведение базовой модели и добавляет к ним свои собственные.Покупатели сообщали в корпорацию Sony, что они хотели бы иметь возможность разговаривать друг с другом во время прослушивания кассеты.Sony усовершенствовала свою модель с двумя разъемами, чтобы люди могли поговорить под музыку. Модель с двумя разъемами и свозможностью ведения переговоров является подклассом модели с двумя разъемами, наследует все ее свойства и добавляет к ним своисобственные.У Sony имеются и другие модели плееров.
Более поздние серии расширяют возможности базовой модели — они создают подклассы на ее основеи наследуют от нее свойства и поведение.Давайте посмотрим, как происходит наследование в Java. Расширим наш класс Point, чтобы он представлял пиксель на экране монитора. В новомклассе Pixel к координатам x и y добавляется информация о цвете пикселя:class Pixel extends Point {Color color;}public void clear() {super.clear();color = null;}Класс Pixel расширяет как данные, так и поведение своего суперкласса Point. Для данных это означает, что в классе Pixel появляетсядополнительное поле color. Pixel также расширяет поведение Point, переопределяя метод clear класса Point.
Эта концепция наглядно изображенана рисунке:Объект Pixel может использоваться в любой программе, которая рассчитана на работу с объектами Point. Если методу необходимо передатьпараметр типа Point, можно вместо него передать объект Pixel — все будет нормально. Вместо объекта класса Point можно пользоватьсяобъектом подкласса Pixel; это явление известно под названием “полиморфизм” — один и то же объект (Pixel) выступает в нескольких (поли-)формах (-морф) и может использоваться и как Pixel, и как Point.Поведение Pixel расширяет поведение Point.
Оно может совершенно преобразиться (например, работа с цветами в нашем примере) или будетпредставлять собой некоторое ограничение старого поведения, удовлетворяющее всем исходным требованиям. Примером последнего можетслужить объект класса Pixel, принадлежащий некоторому объекту Screen (экран), в котором значения координат x и y ограничиваются размерамиэкрана. В исходном классе Point значения координат могли быть произвольными, поэтому ограниченные значения координат все равно лежат висходном (неограниченном) диапазоне.Расширенный класс часто переопределяет поведение своего суперкласса (то есть класса, на основе которого он был создан), по-новому реализуяодин или несколько унаследованных методов. В приведенном выше примере мы переопределили метод clear, чтобы он вел себя так, как тоготребует объект Pixel, — метод clear, унаследованный от Point, знает лишь о существовании полей Point, но, разумеется, не догадывается оприсутствии поля color, объявленного в подклассе Pixel.Упражнение 1.12Напишите набор классов, отражающих структуру семейства плееров Sony Walkman.