аметров командной строки. Пример: программа, печатающая свои аргументы public class myTop { public static void main (String args[]){ int argc = args.length; for (int i = 0; i < argc; i++) System.out.println (argc[i]); } } Аплет выполняется в контексте навигатора и его жизненный цикл определяется следующими методами класса Applet: public void init () вызывается навигатором при загрузка аплета; public void start (); вызывается навигатором при показе страницы; public void stop (); вызывается навигатором, когда тот уходит с Web-страницы; public void destroy (); этот метод предназначен для освобожденя ресурсов; аналог деструктора, но не вызывается автоматически; всегда вызывает stop(); всегда вызывается при выходе из навигатора и при перезагрузке аплета. Простейший аплет выглядит так: 1 import java.awt.Graphics; 2 import java.applet.Applet; 3 class SimpleApplet extends Applet { 4 public void paint (Graphics g) { 5 g.drawString ("Hello world!", 10, 10); 6 } 7 } Метод public void paint (Graphics g) (строки 4-6) определяет, как аплет перерисовывает себя в тот момент, когда оконный ме- неджер посылает WWW-навигатору запрос на перерисовку. Включение аплета в WWW-страницу производится следующим образом. В языке HTML 2.0 предусмотрены специальные конструкции и . Первая из них задает имя загружаемого класса и раз- меры области в окне навигатора, выделяемой аплету. Конструкция служит для передачи информации с WWW-страницы в ту сре- ду, в которой будет выполняться аплет. Ниже приведен простой пример вкллючения аплета в WWW-страницу.

Если вы видите этот текст, то ваш навигатор не поддерживает Java

Поскольку WWW-навигаторы игнорируют неизвестные конструкции, в навигаторе, не поддерживающем Java, будет виден текст -------------------------------------------------------------------------- Если вы видите этот текст, то ваш навигатор не поддерживает Java -------------------------------------------------------------------------- Опросить значения, передаваемые с помощью конструкции , можно следующим образом: public void init () { String fontname = getParameter ("name"); String fontSizestring = getParameter ("size"); int theSize = Int.parseInt (fontSizeString); . . . }  4.2.2. Java-машина Java-компилятор переводит транслирует исходные тексты Java- программ в коды Java-машины. Вообще говоря, Java-машина являет- ся виртуальной в том смысле, что она не существует в виде ре- альных микросхем и других устройств, а представляет собой прог- раммный эмулятор, выполняющийся на какой-либо традиционной ап- паратной платформе. Вероятно, уже в ближайшее время следует ожидать появления и все более широкого распространения и прямых аппаратных реализаций Java-машины. Идея языковых процессоров, разумеется, не нова. Известны попыт- ки внедрить так называемый P-код в качестве стандарта на ре- зультат работы Паскаль-компиляторов; в свое время много писали о языке и машине Форт; была выполнена аппаратная реализация ре- фал-машины, и список этот можно продолжать и продолжать. В контексте проекта Java спецификация виртуальной машины явля- ется частью комплекса мер, направленных на стандартизацию Java- среды и на обеспечение ее независимости от аппаратно-программ- ной платформы. Кроме того, следует учитывать ту специфическую среду, в которой должны готовиться и работать Java-программы. Если Web-страница содержит Java-аплеты, эти аплеты будут пере- даваться по сети. Значит, весьма желательно, чтобы Java-код был как можно более компактным; в противном случае время загрузки страницы рискует стать раздражающе большим. Соответственно, ар- хитектура и система команд Java-машины проектировались таким образом, чтобы всячески способствовать компактификации кода. С другой стороны, формат команд Java-машины довольно прост (обыч- но команды не имеют операндов и занимают один байт), поэтому возможна ее (машины) эффективная эмуляция. По этой причине программы, подготовленные для выполнения на Java-машине, часто называют байт-кодами. Мы опишем архитектуру Java-машины довольно кратко. Последующее изложение опирается на версию спецификаций 1.0.  4.2.2.1. Типы данных, поддерживаемые Java-машиной Java-машина поддерживает следующие стандартные типы данных: - byte - однобайтные целые цисла в двоичном дополнительном коде; - short - двухбайтные целые числа; - int - четырехбайтные целые числа; - long - восьмибайтные целые числа; - float - четырехбайтные вещественные числа в формате IEEE-754; - double - восьмибайтные вещественные числа; - char - двухбайтные беззнаковые символы в кодировке Unicode. Поскольку Java-компилятор в состоянии проверить типы данных во время трансляции, при выполнении нет нужды ассоциировать допол- нительную информацию со значениями стандартных типов. Вместо этого генерируются команды, рассчитанные на обработку данных определенных типов. Например, для сложения целых чисел будет сгенерирована команда iadd, а для сложения вещественных чисел двойной точности - команда dadd. Значения типа boolean представляются однобайтными целыми числа- ми и обрабатываются посредством соответствующих команд. Имеется еще два стандартных типа данных: - object - четырехбайтная ссылка на объект (массивы трактуются как объекты); - returnAddress - четырехбайтный адрес возврата из метода. Спецификации Java-машины не описывают внутренней структуры об- ъектов. В реализации Sun Microsystems значение типа object ука- зывает на описатель, хранящий две ссылки - на таблицу методов и на данные объекта. Возможны и другие представления. Java-машина является 32-разрядной. Более длинные значения (long, double) представляются как пара четырехбайтных величин. Не оговоривается, в каком порядке располагаются элементы пары; более того, верификатор байт-кодов обязан выявлять и отвергать программы, пытающиеся "вручную" составлять длинные значения.  4.2.2.2. Регистры В Java-машине должны поддерживаться следующие регистры: - pc - счетчик команд; указывает на код операции для команды, которая будет выполняться следующей. - vars - базовый регистр для доступа к локальным переменным те- кущего метода. - optop - указатель на вершину стека операндов. Java-машина яв- ляется стековой, поэтому основная часть команд берет операнды из стека и туда же помещает результат. - frame - указатель на структуру, содержащую окружение времени выполнения. В свою очередь, окружение времени выполнения используется для реализации трех целей: динамической загрузки, возврата из мето- дов и обработки исключительных ситуаций. Для обеспечения динамической загрузки, окружение времени выпол- нения содержит ссылки на таблицу сивмолов текущего метода и те- кущего класса. Перед началом выполнения метода выполняется ре- дактирование его внешних связей (настройка ссылок на внешние методы и внешние данные). Подобная поздняя настройка ссылок де- лает сгенерированный код устойчивым по отношению к изменениям во внешних классах. Для обеспечения нормального возврата из методов выполняется восстановление регистрового окружения вызывающего метода. Для обработки исключительных ситуаций Java-машина выполняет проход по стеку вызова методов и отыскивает самую внутреннюю конструкцию catch, обрабатывающую случившееся событие. В принципе окружение времени выполнения может содержать допол- нительную информацию, необходимую, например, для отладки, но в спецификациях Java-машины это оставлено на усмотрение авторов реализации.  4.2.2.3. Сбор мусора Для создания объектов во время выполнения выделяется область динамической памяти. Язык Java рассчитан на то, что эту область обслуживает сборщик мусора, поскольку в языке нет средств для освобождения памяти. Как именно работает сборщик мусора, опре- деляется реализацией Java-машины.  4.2.2.4. Система команд Java-машины Команда Java-машины состоит из однобайтного кода операции, за которым следуют операнды (если таковые имеются). Можно выделить следующие группы команд: - команды загрузки констант и переменных в стек операндов. Для каждого типа данных имеются свои команды загрузки. Например, команда с кодом операции dload и операндом, задающим смещение, загружает в стек из локальной переменной вещественное число двойной точности, а команда aload делает то же для ссылки на объект. - команды запоминания данных из стека в локальных переменных. - команды управления массивами. Например, команда newarray с операндом, задающим тип элементов, извлекает из стека требуемый размер массива, создает его и помещает в стек ссылку на массив. Отметим, что для создания массивов с элементами-объектами слу- жит другая команда, anewarray. За счет подобной специализации достигается эффективность интерпретации Java-программ. - команды работы со стеком. К этой группе относятся команды, которые удаляют, дублируют, меняют местами верхние элементы стека операндов, а также выполняют другие, более сложные мани- пуляции со стеком. - арифметические команды. Операнды извлекаются из стека; туда же помещается результат. - логические команды (сдвиг, и, или, исключающее или). - команды преобразования к другому типу. - команды передачи управления. Например, в команде jsr (переход на подпрограмму) операндом служит относительный адрес перехода; адрес команды, следующей за jsr, помещается на вершину стека операндов. Имеются команды для реализации переключателей. - команды возврата из функции. Для возврата результатов разных типов используются команды с разными кодами операции. Кроме то- го, имеется команда breakpoint, которая останавливает нормаль- ный ход выполнения и передает управление обработчику этого со- бытия. - команды манипулирования с полями объектов (установить/прочи- тать обычное/статическое поле). - команды вызова методов. Их четыре. Команда invokevirtual вы- зывает (виртуальный) метод на основе анализа информации времени выполнения. Команда invokenonvirtual осуществляет вызов на ос- нове информации времени компиляции - например, вызов метода ро- дительского класса. Команда invokestatic вызывает статический метод класса. Наконец, команда invokeinterface вызывает метод, представленный интерфейсом. Выполнение всех перечисленных ко- манд связано не только с передачей управления, но и с анализом разного рода таблиц. - команда возбуждения исключительной ситуации - athrow. - прочие объектные операции (создать объект, проверить тип об- ъекта). - команды сихронизации (войти в критический интервал, выйти из него). Мы видим, что не существует семантического разрыва между языком Java и Java-машиной. Как уже отмечалось, это важно для компакт- ности скомпилированных Java-программ и для обеспечения высокой скорости трансляции.  4.2.3. Java и безопасность Концепция загрузки объектов по сети прозрачным для пользователя образом столь же привлекательна, сколь и опасна. Если не предп- ринимать никаких мер и не накладывать никаких ограничений на возможности Java-аплетов, вход на любую Web-страницу может при- вести к непредсказуемым последствиям. К счастью, разработчики языка Java с самого начала уделяли самое пристальное внимание вопросам информациионной безопасности. Из языка удалены многие потенциально опасные возможности, такие как оператор goto или тип данных "указатель". Интерпретируемый характер выполнения позволяет не допустить выхода за границы массива, обращения по пустой ссылке и т.п. В свое время за по- добную осторожность выступал автор языка Паскаль Никлаус Вирт, отмечавший, что при традиционном подходе программист напоминает моряка, который носит спасательный круг только на суше. Мы, однако, не будем подробно останавливаться на "обычной" бе- зопасности и уделим основное внимание выполнению потенциально враждебных аплетов. Смежный вопрос - проверка подлинности апле- тов, снабженных электронной подписью, видимо, будет решен в последующих версиях Java-систем. Прежде всего, аплетам, загруженным по сети, запрещены чтения и запись файлов из локальной файловой системы, а также выполнение сетевых соединений со всеми хостами, кроме того, с которого был получен аплет. Кроме того, таким аплетам не разрешается запус- кать программы на клиентской системе (говоря языком ОС UNIX, для них недоступны системные вызовы fork и exec), им запрещено загружать новые библиотеки и вызывать программы, внешние по от- ношению к Java-машине. На самом деле, перечисленные ограничения не являются частью спецификации Java-системы и могут выполняться с большей или меньшей аккуратностью. Так, в Netscape Navigator 2.0 чтение и запись локальных файлов действительно полностью запрещены. В то же время, среда разработки JDK 1.0 компании Sun Microsystems допускает задание списка каталогов, с которыми аплеты могут ра- ботать. Более точно, вне разрешенного списка каталогов аплет не может: - проверять существование файлов; - читать/писать/переименовывать файлы; - создавать каталоги; - проверять атрибуты файла - тип, время последней модификации, размер. Чтобы в JDK сделать каталог доступным для аплета, следует по- местить в файл ~/.hotjava/properties строки вида acl.read=/home/welcome acl.write=/tmp Перед началом работы аплетов они проверяются верификатором бай- т-кодов. Верификатор убеждается, что загруженный аплет соот- ветствует спецификациям, заданным при компиляции вызывающей программы, что не нарушен формат скомпилированного файла, что нет переполнения или исчерпания стека, нет некорректных преоб- разований типов, неправильных действий с регистрами и т.п. Все эти проверки верификатор осуществляет на основе анализа потоков данных. Особенно тщательно проверяются конструкции finally об- работчиков исключительных ситуаций. Следует отметить, что верный выбор баланса между возможностями загружаемых аплетов и безопасностью клиентской системы является очень тонким вопросом. Ряд компаний, например, Argus System Group, предлагают реализовать на клиентской системе усиленные меры безопасности, чтобы успешно отражать угрозы со стороны враждебных аплетов без ограничения свободы действий для "благо- надежных" программ. К сожалению, предлагаемые решения зависят от операционной платформы, что противоречит требованию абсолют- ной переносимости Java-программ. Можно предположить, что инфор- мационная безопасность еще долгое время будет оставаться одним из самых сложным и спорных вопросов, касающихся проекта Java.  4.2.4. Java WorkShop В конце марта 1996 года компания Sun Microsystems объявила о выпуске версии 1.0 среды разработки Java WorkShop. У этой среды есть два замечательных свойства: она полностью написана на язы- ке Java и имеет интерфейс, выдержанный в Web-стиле. На рис. y1 показан вид экрана при работе в Java WorkShop. Рис. y1. Так выглядит экран при работе в Java WorkShop. Следует отметить, что гипертекстовый интерфейс является, пожа- луй, наиболее естественным для инструментальных сред. Более то- го, неявно он давно используется, например, при переходе во включаемый файл или в место ошибки. Принципиально важно, что теперь гипертекст стал явной концептуальной основой. Java WorkShop содержит полный набор инструментов, необходимых для проектирования, разработки, тестирования, отладки и сопро- вождения программ. В его состав входят: - Менеджер проектов - инструмент организации информации, сос- тавляющей проект, а также средство спецификации окружения для проекта. - Построитель - инструмент построения результирующих программ проекта. Построитель ведает перекомпиляцией файлов после внесе- ния изменений, выдачей гипертекстового списка сообщений об ошибках и т.п. - Публикатор - инструмент поддержки коллективной работы над проектами. Позволяет организовать хранилище проектов, предос- тавлять Web-страницы проектов для использования другими прог- раммистами, осуществлять доступ к проектам коллег, задавать права доступа к проектам. - Просмотрщик аплетов - средство контролируемого выполнения Java-программ. - Просмотрщик исходных текстов - инструмент изучения программ с учетом их объектной структуры. - Редактор исходных текстов. Редактор интегрирован с другими компонентами Java WorkShop, а также с популярными системами уп- равления версиями. - Отладчик. Помимо традиционных возможностей, отладчик Java WorkShop позволяет контролировать состояние нескольких потоков выполнения, что необходимо для развитых Java-программ. На рис y2 представлен образ экрана при работе в отладчике. Рис. y2. Так выглядит экран при работе с отладчиком Java WorkShop. - Справочная подсистема. Java WorkShop может работать как на платформе SPARC/Solaris и Intel/Solaris, так и под Microsoft Windows 95/NT. Каких-то осо- бых требований к аппаратуре Java WorkShop не предъявляет. Дос- таточно 45 Мб дискового пространства, 32 (для Solaris) или 16 (для Windows) Мб оперативной памяти. Замечательно, как в правильно спроектированной системе различ- ные компоненты не просто идеально подходят друг к другу но и усиливают мощь друг друга.  * 4.3. Связь Java с окружением: оконный инструментарий  4.3.1. Общие положения Одно из важных достоинств Java состоит в том, что это не только язык, но и стандартизованная объектно-ориентированная среда вы- полнения. Любопытно проследить, как в рамках Java решаются тра- диционные программистские проблемы. Мы остановимся на оконном графическом интерфейсе. Вместе с различными приятными (главным образом для пользовате- ля) свойствами, оконный интерфейс привносит и довольно неприят- ные (для разработчика) проблемы. Одна из них - это переноси- мость приложений между разными платформами. Переносимость явля- ется проблемой и без графического интерфейса, однако наличие такового делает ее многократно сложнее. Дело в том, что каждая оконная среда - это сложный мир, со сво- ими законами, набором строительных блоков и приемов программи- рования. Motif не похож на MS-Windows и оконную систему Macintosh. По-разному представляются примитивные элементы ин- терфейса, по-разному обрабатываются внешние события, по-разному происжодит рисование на экране и т.д. Вместе с тем, по своей сути оконная среда - просто идеальное поле деятельности для объектного программирования. Даже челове- ку, неискушенному в объектно-ориентированных методах проектиро- вания, ясно, что такие вещи, как кнопки, текстовые поля, меню, вполне заслуживают названия объектов, как бы это слово ни пони- малось. Иначе говоря, вполне понятно, что такое "кнопка вооб- ще", "список вообще" и т.д. Все это дает основания надеяться, что с помощью объектно-ориен- тированного подхода можно получить по-настоящему высокоуровне- вую и переносимую оконную среду, основанную на абстрактных ти- пах данных. Данная особенность оконных сред проявилась, в частности, в по- явлении довольно большого количества различных классовых библи- отек, "обертывающих" оригинальные оконные системы. В качестве примеров можно привести MFC, OWL, Zink и многие другие. Вот и среди стандартных Java-библиотек присутствует AWT или Abstract Windowing Toolkit - абстрактный оконный инструмента- рий. AWT является системой классов для поддержки программирования в оконной среде. Его "абстрактность" проявляется в том, что все, зависящее от конкретной платформы, хорошо локализовано и спря- тано. В AWT реализованы такие простые и понятные вещи, как кнопки, меню, поля ввода; простые и понятные средства организа- ции интерфейса - контейнеры, панели, менеджеры геометрии. Это хорошо видно на рис. x1. Рис. x1. Основные элементы иерархии классов AWT. Все зависимости от платформы содержатся в ветви, обозначенной как Peer. Далее мы рассмотрим некоторые особенности AWT, не претендуя на полноту изложения. Наша цель - дать общее ппредставление о тех- нологии программирования графического оконного интерфейса в среде Java.  4.3.2. Из чего строится графический интерфейс (компоненты и контейнеры) Если посмотреть на любое оконное приложение, то легко увидеть, что интерфейсная часть состоит из объектов, объединенных в группы. В AWT объекты называются компонентами (на самом деле они все являются наследниками класса Component), а группы об- ъектов реализованы с помощью так называемых контейнеров. Отме- тим, что любой контейнер - это тоже компонента, поэтому группы объектов могут быть вложены друг в друга. Как обычно, меню сто- ят особняком. Иерархия компонент показана на рис. x2. (Автором этого и двух следующих рисунков является Charles L. Perkins, clp@home.HarvardSq.com.) Рис. x2. Иерархия компонент AWT На рис. x3 поясняются обозначения, использованные на рис. x2. К числу примитивных компонент относятся: - Button - Checkbox - Label - List - ScrollBar - TextArea - TextField Основные контейнеры: - Dialog - FileDialog - Frame - Panel - Window Взаимодействие интерфейсных компонент с пользователем реализо- вано с помощью аппарата событий, о котором будет рассказано ни- же.  4.3.3. Как организовать интерфейс Мы уже отмечали, что интерфейс состоит из компонент, помещенных в контейнеры. Однако, остается открытым вопрос о том, как раз- мещать компоненты друг относительно друга внутри контейнера. Наивный подход (принятый, тем не менее, во многих системах) заключается в задании относительных координат компонент в кон- тейнере. Вариации этого подхода состоят, как правило, в возмож- ности задавать различные единицы длины (пикселы, тысячные дюй- ма, "диалоговые единицы"). Недостатком подобной модели размеще- ния компонент является то, что при переводе приложения на дру- гую платформу и даже на другой компьютер, внешний вид приложе- ния меняется плохо предсказуемо. AWT старается решить данную проблему следующим образом. Если нельзя избежать изменений внешнего вида приложений при запуске их на разных платформах, надо постараться хотя бы сделать эти изменения предсказуемыми и в некотором смысле естественными. Для проведения этой программы в жизнь используются объекты под общим названием Layout (расположение). Layout управляет тем, как компоненты будут располагаться внутри контейнера, следуя определенным принципам или рецептам. Всего в AWT имеется 5 предопределенных расположений: - BorderLayout - CardLayout - FlowLayout - GridLayout - GridBagLayout Их местоположение в иерархии классов показано на рис. x4. Рис. x4. Расположения и иерархия классов AWT. Расположения являются прямыми наследниками класса Object и все реализуют протокол LayoutManager. Объект типа LayoutManager содержится в классе Container. В классе Container определены 3 метода add, предназначенные для добавления новых компонент в контейнер. Куда именно будет до- бавлена компонента с помощью метода add, зависит от конкретного типа LayoutManager данного контейнера. Для задания LayoutManager есть метод setLayout. Рассмотрим кратко, как работают приведенные выше схемы размеще- ния.  4.3.3.1. BorderLayout BorderLayout делит прямоугольный контайнер на 5 прямоугольных областей: север, юг, запад, восток и центр: [Image] Компонента добавляется в соответствующую область с помощью ме- тода add (string, component); Пример. setLayout (new BorderLayout()); buttonN = new Button ("one"); add ("North", buttonN); // ... добавление остальных кнопок  4.3.3.2. CardLayout [Image] Контейнер состоит из нескольких плоскостей. В каждый момент на- верху только одна плоскость. Таким образом, CardLayout предс- тавляет собой как бы блокнот со многими страницами. Cтраницы помечаются с помощью строк. Метод добавления компонент к контейнеру: add (string, component); где string - имя "страницы", а component - добавляемая компо- нента. Как правило, эти компоненты сами будут контейнерами (страница блокнота врядли будет состоять из одной большой кноп- ки): setLayout (new CardLayout ()); add ("one", create (new FlowLayout ())); add ("two", create (new BorderLayout ())); add ("three", create (new GridLayout (2, 2))); add ("four", create (new BorderLayout (10, 10))); add ("five", create (new FlowLayout (FlowLayout.LEFT, 10, 10))); add ("six", create (new GridLayout (2, 2, 10, 10)));  4.3.3.3. FlowLayout FlowLayout реализует модель построчного заполнения контейнера. После заполнения одной строки начинается следующая. При измене- нии размеров контейнера происходит перераспределение компонент по строкам. [Image] setLayout (new FlowLayout ()); add (new Button ("OK")); add (new Button ("Cancel")); add (new Button ("Resume")); Новые компоненты добавляются в контейнер с помощью метода add (component). Ряды компонент могут быть выравнены вправо, влево, или центри- рованы.  4.3.3.4. GridLayout Контейнер разбивается на клетки. Для этого задается число строк и столбцов. При добавлении новых компонент, клетки заполняются по строкам. Возможность делать пропуски отсутствует. Новые компоненты добавляются в контейнер с помощью метода add (component) [Image] Пример. setLayout (new GridLayout (2, 3)); // 2 строки, 3 столбца add (new Button ("1")); add (new Button ("2")); add (new Button ("3")); add (new Button ("I")); add (new Button ("II"));  4.3.3.5. GridBagLayout GridBagLayout позволяет разделить контейнер на неравные прямоу- гольные области. Это достигается с помощью объединения соседних клеток в клетки большего размера. Кроме того, GridBagLayout позволяет заполнять решетку с пропусками. Конкретный алгоритм заполнения определяется объектом класса GridBagConstraints. В объектах этого класса имеется более 10 параметров, определяю- щих размещение следующей компоненты. Программа, использующая GridBagConstraints, может выглядеть следующим образом: GridBagLayout gridbag = new GridBagLayout (); GridBagConstraints c = new GridBagConstraints (); setLayout (gridbag); // Устанавливаем характеристики c.fill = GridBagConstraints.BOTH; c.weightx = 1.0; . . . Button button1 = new Button ("1"); gridbag.setConstraints (button1, c); add (button1); . . . // здесь можно изменить некоторые установки // объекте класса GridBagConstraints, // например // c.fill = GridBagConstraints.NONE; Button buttonX= new Button ("X"); gridbag.setConstraints (buttonX, c); add (buttonX);  4.3.4. События В AWT, как и в других оконных средах, события как программные объекты соответствуют внешним событиям. Типичный пример - нажа- тие на кнопку, в результате чего в AWT происходит событие ACTION_EVENT. Таким образом, интерактивная часть программ в AWT соответствует модели программы, управляемой событиями. Другими словами, при- ложения или аплеты должны отслеживать события и обрабатывать их. Рассмотрим подробнее, как это происходит в AWT. Каждый оконный интерфейс можно рассматривать как набор (возможно, вложенных друг в друга) компонент. Когда происходит событие, связанное с каким-то элементом интерфейса (например, кнопкой), то вызывает- ся метод handleEvent. По умолчанию этот метод ничего не делает, а просто передает событие наверх, то есть тому объекту, в кото- ром содержится инициатор события (например, объемлющему окну). Таким образом, если событие никто не перехватывает, оно дости- гает фрейма (если это приложение) или аплета. Этот базовай механизм обработки событий при наивном применении навязывает программисту одну из двух моделей обработки событий. - Во-первых, можно позволить всем событиям всплывать до самого верха и уже на уровне фрейма писать метод, который занимается разбором и обработкой событий. - Во-вторых, можно создать множество специализированных клас- сов, в каждом из которых переопределен метод handleEvent. Оба этих крайних подхода небезупречны. Первый способствует на- писанию монолитных программ, второй приводит к очень большому числу классов. В реальной жизни используется компромиссная идеология - handleEvent переопределяется для составных объектов, объединяю- щих несколько элементов интерфейса и отвечающих за ясно опреде- ленную часть работы приложения (например, разного рода диало- ги). Кроме того, возможны и другие модели обработки событий, направ- ленные на лучшее отделенин логики программы от ее интерфейса. В качестве одного из примеров реализации альтернативной модели можно указать пакет "The Command Class for AWT objects", кото- рый написал Jan Newmarch, jan@ise.canberra.edu.au.  4.3.5. Методы класса Component, связанные с обработкой событий Ниже перечислены методы класса Component, связанные с обработ- кой событий. - postEvent(). Этот метод, как правило, вызывается автоматичес- ки при наступлении соответствующего события. - Обрабатываются события при помощи метода handleEvent(). По умолчанию этот метод, в зависимости от типа события, вызывает один из специализированных обработчиков событий, таких как - - action() - - keyUp() - - mouseDown() - - gotFocus() и т.д. Метод handleEvent() может быть переопределен. В этом случае, как правило, вся обработка соответствующего события будет про- исходить именно в этом методе, однако, если handleEvent() возв- ращает false, то вызывается handleEvent() для контейнера, со- держащего данную компоненту. События в AWT представляются с помощью объектов класса Event, в котором определены следующие переменные: public Object target; // инициатор события public long when; // время, когда событие произошло public int id; // тип события(KEY_PRESS, MOUSE_DOWN...) public int x; // координаты public int y; // курсора public int key; // код клавиши public int modifiers;// код модификатора (control, shift ...) public Object arg; // вспомогательные данные public Event evt; // поле для соединения событий в списки Приведем типичный пример обработки событий, когда все они обра- батываются на верхнем уровне (в данном случае на уровне апле- та). class MyApplet extends Applet { . . . public boolean action( Event evt, Object arg) { . . . if ((ev.target instanceof Button) && arg.equals ("OK")) { // Выполнить соответствующие действия . . . return true; } else { // Другие случаи . . . } . . . return false; } . . . } В этом примере, если инициатор события имеет тип Button с име- нем "OK", то выполняются соответствующие действия и возвращает- ся значение true, то есть событие дальше не передается. Другой способ обработать событие заключается в создании специа- лизированной компоненты. Пример. class OKButton extends Button { . . . public boolean action (Event e, Object arg) { // Выполнить соответствующие действия . . . return true; } } Мы видим, насколько глубоко продумана в проекте Java связь с операционным окружением. Удалось достичь удачного сочетания бо- гатства возможностей с переносимостью. 5. Joe - технология связывания Java-программ с объектными бизнес-приложениями Выше, в разделе "Java, Joe и NEO", мы писали о том, что новый продукт компании SunSoft - Joe - призван осуществлять связь между клиентскими компонентами, написанными на языке Java, и объектными серверами приложений, созданными в среде NEO. При этом Joe берет на себя все (или почти все) технические пробле- мы, связанные с работой в распределенной объектной среде, обес- печивая в то же время для Java-программ полноценное взаимодей- ствие с произвольными объектными сервисами. В предыдущих выпусках Jet Info была опубликована шутливая "Эво- люция программиста". Мы добавим к ней еще два раздела. Первый из приводимых ниже примеров написан на языке Java и можеи ис- пользоваться в составе обычных, локально работающих аплетов. 1 import java.awt.Font; 2 import java.awt.Color; 3 public class JAVAhello extends java.applet.Applet { 4 Font f = new Font ("TimesRoman", Font.BOLD, 36); 5 public void init () { 6 resize (150, 25); 7 } 8 public void paint (Graphics g) { 9 g.setFont (f); 10 g.setColor (Color.blue); 11 g.drawString ("Hello, World!", 50, 25); 12 } 13 } Теперь модифицируем программу для Joe, чтобы обеспечить возмож- ность работы в среде клиент/сервер. 1 import sunw.services.*; 2 import java.awt.Graphics; 3 import java.awt.Font; 4 import java.awt.Color; 5 public class JOEhello extends sunw.services.JOEApplet { 6 sunw.corba.ObjectRef obj; 7 Hello.HelloWorldRef hiThere; 8 Font f = new Font("TimesRoman", Font.BOLD, 36); 9 public void init () { 10 super.init (); 11 resize (150, 25); 12 obj = find ("HelloWorldServer"); 13 hiThere = Hello.HelloWorldStub.narrow (obj); 14 } 15 public void paint (Graphics g) { 16 g.setFont (f); 17 g.setColor (Color.red); // Получим строку из удаленного объекта, реализованного на C++, // и выведем ее. 18 g.drawString (hiThere.sayHello (), 50, 25); 19 } 20 } Поясним смысл новых строк, появившихся во втором варианте прог- раммы. В строке 1 импортируется описание предоставляемых объектных сервисов. В строке 5 объявляется, что класс Hello будет наследником JOEApplet. В строке 6 декларируется обобщенная (не типизированная) ссылка на NEO-объект. Она будет использована для сохранения результата поиска объекта по имени. В строке 7 описана типизированная ссылка на NEO-объект, которая будет использоваться для манипулирования удаленным объектом (в частности, для вызова методов) средствами языка Java. В строке 12 мы получаем от службы имен NEO ссылку на нужный нам серверный объект. В строке 13 выполняется операция приведения обобщенной ссылки к типизированному виду. Наконец, в строке 18 выполняется вызов метода удаленного объек- та, написанного, вообще говоря, не на языке Java (например, на C++). Впрочем, вид этого оператора не зависит ни от удаленнос- ти, ни от языка реализации объекта. Процесс разработки программ в среде Joe довольно прост. Он сос- тоит из следующих этапов: - Трансляция интерфейса к NEO-объектам, написанного на языке IDL (Interface Definition Language), в класс на язык Java. Этот этап поддержан входящим в состав Joe компилятором IDL - Java. Результат трансляции содержит суррогатные методы, которые во взаимодействии с брокером объектов обеспечивают взаимодействие с удаленными объектами, не отличающееся от локального случая. В свою очередь, брокер объектов, входящий в состав Joe, прозрач- ным для клиентской стороны образом загружается в WWW-навигатор вместе с Java-аплетами. - Написание клиентского кода на языке Java с использованием сгенерированного интерфейса и средств Joe для взаимодействия с удаленными объектами. Дальше Java-программа компилируется и выполняется обычным обра- зом. Подчеркнем, что описанная объектная среда обеспечивает полно- ценное, двустороннее взаимодействие между клиентом и сервером. В частности, удаленные серверные объекты могут вызывать методы в объектах-клиентах. Для обеспечения этой возможности в составе Joe имеется транслятор Java-классов в IDL-интерфейсы. 6. Заключение Интранет и Java - вот два ключевых слова, символизирующих сов- ременный этап развития информационных технологий. Интранет поз- воляет пересмотреть подход к пользованию информационными ресур- сами, что в огромной степени увеличивает производительность труда отдельных работников и компаний в целом. Кроме того, тех- нология Интранет позволяет добиться невиданной ранее масштаби- руемости - от локальной сети до Интернет. Java снимает ограничения Web-сервиса, делая последний интерак- тивным и объектно-ориентированным. Java вводит новый - абсолют- ный - стандарт на переносимость программного обеспечения. При- мечательно, что беспрецедентные по своей мощи возможности вво- дятся при полном сохранении информационной безопасности. В сочетании с продуктами Sun Microsystems - Joe и NEO - Java обеспечивает распространение концепции Интранет на произвольные сервисы, что открывает реальную возможность создания корпора- тивных информационных систем нового поколения. ------------------ Артур ван Хофф получил образование в Голландии, затем работал в ведущих европейских компьютерных компаниях. В течение трех лет, начиная с 1993 года, работал в Sun Microsystems. Артур ван Хофф принимал участие в разработке языка Java, в проектировании программного интерфейса для приложений на Java, им написан пер- вый Java-компилятор на языке Java. В 1996 году он и его коллеги Сэми Шайо и Ким Полезе образовали независимую компанию с намерением разрабатывать программное обеспечение на Java. Артур ван Хофф принимает активное участие в популяризации Java, он участвует в наиболее известных конференциях и является авто- ром ряда статей и готовящейся к изданию весной 1996 года книги "Hooked on Java". Вопрос. Internet, Web и Java представляют собой сдвиг парадигмы в информационных технологиях. Общественная реакция на этот сдвиг не имеет прецендента в компьютерной индустрии - ведущие компании объявили о поддержке Java, на эту тему в компьютерной и деловой прессе было опубликовано невероятное количество ста- тей, стоимость акций тех компаний, которые связаны с этими тех- нологиями, резко подскочила, технические руководители банков и крупных корпораций поддерживают применение Java в пилотных про- ектах. В то же время все существующие сегодня приложения этих техноло- гий ограничены в основном небольшими задачами, такими как мар- кетинг в Internet, распространение информации, Java-игры и т.д. И даже предполагаемые в будущем приложения не отличаются ради- кальной новизной. Что же особенного в этих технологиях, чем можно на самом деле объяснить те реакцию и интерес, которые мы можем наблюдать се- годня? Ответ. Соврешенно очевидно, что Java и Internet представляют собой целый мир новых возможностей для компьютерной индустрии, однако существующие сегодня приложения пока остаюся простыми, потому что еще нет соответствующего опыта в решении некоторых внутренних проблем. Тем не менее, рынок очень быстро сдвигается в направлении этого нового мира, ежедневно объявляются новые продукты и технологии. Именно это и свидетельствует о том, что Java и Internet представляют собой огромный сдвиг парадигмы, создающий новые возможности. Это событие сравнимо по масштабу с появление пероснальных компьютеров, но сегодня оно захватило всех гораздо быстрее. В чем же специфика Java и Internet? Я думаю, что они в состоя- нии обеспечить компьютерной индустрии и пользователям именно то, чего те всегда ожидали: простой доступ к неограниченным об- ъемам информации и приложений. Вопрос. Как любая технология, Java имеет союзников и оппонен- тов. Кто, по Вашему мнению, представляет наибольшую опасность для будущего Java (продукт, компания или кто-то лично)? Каковы могут быть ответные конкурирующие начинания оппонетов Java? Ответ. Наибольшая опасность состоит в том, что в ближайшие годы мы должны прийти к новой среде, целиком написанной на Java, но с библиотеками от разных поставщиков. Это значит, что мы полу- чим лишь новый, улучшенный язык реализации и ничего более. За- дача же состоит в том, чтобы создать общепринятую среду, не за- висящую от платформы. В то же время, было бы глупо с моей стороны, будучи стронником Java, делиться с моими оппонентами идеями о том, как строить атаку на Java, не так ли? Вопрос. Каким будет влияние сдвига компьютерной парадигмы, представленной Internet, Web и Java, на основных действующих лиц текущей прадигмы (IBM, Sun, HP, DEC, Compaq, Oracle и дру- гих)? Ответ. В современных условиях покупка компьютера приводит к по- жизненной необходимости для владельца покупать программное обеспечение у одного поставщика. Это не может длиться бесконеч- но. Если все компьютеры смогут выполнять любое програмное обес- печение на Java, то замок, в виде привязанности к определенной платформе, будет снят и такие монополисты, как Microsoft, будут вынуждены сражаться на равных с более мелкими фирмами. Таким образом будет выровнено игровое поле и возникнет среда с боль- шими возможностями для конкуренции, а результатом, в конечном итоге, будут продукты лучшего качества, в большей степени ори- ентированные на потребителя. Вопрос. Россия, наряду с Китаем и Индией, - одна из стран, хо- рошо известных высоким профессинальным уровнем программистов. К сожалаению, российские программисты опоздали к первой волне "гаражных компьютеров" в начале 80-х годов. Затем наступила по- лоса доминирования на рынке больших компаний, попасть на рынок и добиться каких-то успехов стало практически невозможно. Широ- ко распространено мнение о том, что с приходом Java возникнет новая волна "гаражного программирования", и в ней смогут приять участ