Запущен проект "Память+"
Читать здесь
Предыдущее занятие | Следущее занятие |
Продолжаем изучение языка программирования Java. На прошлом занятии была сделана программа, которая проверяет является ли введенное число простым. Сегодня мы спроектируем на Java целую систему орошения (виртуальную конечно), состоящую из нескольких классов, и на ее примере разберем следующие важные для понимания этого языка вопросы:
Еще поговорим о методе toString() и о "примитивных" типах.
Несколько слов о композиции и повторном использовании кода. Думается, что использование компьютера в качестве средства автоматизации - это отличная идея, и компьютер изобретен, в конечном счете, для этого. Ведь мы же копируем информацию из текстового файла, сделанного нами ранее или из файла друга, в свой новый файл (конечно, если друг не против этого). В данном случае мы повторно используем работу, сделанную нами или нашим другом для создания нового продукта (в данном случае - текстового файла).
В среде программистов происходит примерно тоже самое. Если программисту удалось сделать удачный класс Java для решения какой-либо задачи и возможно его применение в других программах, то есть смысл оформить его как законченный модуль и применять этот код повторно. Класс - это и есть единица законченного модуля в Java (см. наше занятие о пакетах) .
Давайте разберем один из вариантов повторного использования кода в Java, который называется "композиция".
Листинг 1. Файл SprinklerSystem.java
Итак, смотрим файл SprinklerSystem.java из Листинга 1. Наша программа состоит из двух классов: основного - SprinklerSystem (собственно сама система орошения) и вспомогательного WaterSource (источник воды). И в качестве поля класса SprinklerSystem, наряду с строковыми полями valve1, valve2, valve3, valve4 (valve - это кран или вентиль в нашей системе), полем целочисленного типа int - i и полем типа double - f используется поле с названием source, являющееся экземпляром класса WaterSource.
Оказывается, наряду с полями, являющимися так называемыми "примитивными" типами языка Java (int, double и т.д.), в качестве поля класса может быть использован экземпляр другого класса. Если быть честным, то тип String - это тоже представитель классов Java, только этот класс разработан уже не нами, а создателями языка. В Занятии 5 мы говорили также о выделении памяти для объектов. И если в состав класса входит экземпляр другого класса, то точно также, при создании нового объекта, память выделяется и для него. А код "внедряемого" объекта просто включается в новый класс (отсюда собственно и название такого метода повторного использования кода).
Для простоты наш класс WaterSource, который используется для композиции, содержит всего два метода - конструктор, который просто выводит с помощью System.out.println() строку с названием конструктора класса "WaterSource()" и метод toString(), который возвращает значение строковой переменной s. Интересно, что метод toString() мы определили и для основного класса. Ничего удивительного, ведь этот метод используется в Java в тех случаях, когда компилятор располагает не объектом, а, процитируем Эккеля:
"хочет получить его строковое представление в формате String. Поэтому в выражении метода SprinklerSystem.toString() " source=" + source; компилятор видит, что к строке " source=" прибавляется объект класса WaterSource. Компилятор не может это сделать, поскольку к строке можно "добавить" такую же строку, и преобразует объект source в String вызывая метод toString()...Чтобы подобное поведение поддерживалось вашим классом, достаточно включить в него метод toString()." |
Поговорим теперь о значениях по умолчанию для полей классов. В терминах ООП процесс присвоения полю или переменной к.л. начального значения называют "инициализацией". Если скомпилировать этот пример и посмотреть на вывод программы, то мы увидим, что примитивные типы, определенные в качестве полей класса (переменная i) автоматически инициализируются нулевыми значениями. Ссылки на объекты заполняются значениями null, и при попытке вызова метода по этой ссылке произойдет исключение или по-просту - "произойдет ошибка во время исполнения программы". Однако, как оказалось, такую ссылку можно вывести на экран с помощью метода System.out.println.
ВОПРОС: после компиляции и выполнения программы (обязательно сделайте это) чему равно значение переменной valve2? Почему? |
Компилятор не создает объекты для переменных класса и ссылок "по-умолчанию", и это логично, потому что во многих случаях это привело бы к лишним затратам ресурсов. Если нужно проинициализировать переменную - присвойте ей значение в конструкторе (как для f, valve2), ссылку на объект (класс) - воспользуйтесь оператором new.
В заключении, приведем в таблице примитивные типы Java, хоть мы еще и не со всеми познакомились:
Примитивный тип | Размер занимаемой памяти, бит | Минимум | Максимум |
---|---|---|---|
boolean (логическое значение) | - | - | - |
char (символьное значение) | 16 | 0 | 216-1 |
byte (байт) | 8 | -128 | +127 |
short (короткое целое) | 16 | -215 | +215-1 |
int (целое) | 32 | -231 | +231-1 |
long (длинное целое) | 64 | -263 | +263-1 |
float (число с плавающей запятой) | 32 | IEEE754 | IEEE754 |
double (число с повышенной точностью) | 64 | IEEE754 | IEEE754 |
void ("пустое" значение) | - | - | - |
Примечания: * для определения максимального значений переменных примитивных типов используется известная в информатике формула Хартли N = 2i, где i - размер переменной в битах, плюс необходимо учитывать еще знак переменной;
* IEEE754 - стандарт для представления чисел с плавающей запятой
Числа с плавающей точкой/запятой согласно стандарту IEEE754-2008, исчерпывающая информация
По ссылке ниже можно скачать пример класса Car, подсмотренного на просторах Интернета и немного переработанного, где с помощью нескольких вспомогательных классов показаны различные способы выполнения полезных действий в программе с использованием метода композиции. Скачать файл Car.java
1. Брюс Эккель "Философия Java", 4-е издание, Глава 7 "Повторное использование классов", параграф - "Синтаксис композиции" с.170