Интернет
Горячий кофе за 55 минут
Сергей Королев
Все-таки в несколько приемов у меня получилось скачать через Internet новое чудо – навигатор HotJava * фирмы Sun: 3,9 мегабайта – это не шутки! Успешный сеанс связи длился 55 минут.
Сразу видно, что это "альфа" – сообщение о том, что "This program has performed an illegal operation приходится видеть довольно часто. Однако на это можно не обращать внимания – навигатор ценен тем, что вместе с ним приходит, во-первых, целая куча документации, в том числе спецификация нового объектно-ориентированного языка Java, а во-вторых, сам компилятор языка Java, так что можно немедленно приступать к написанию всевозможных "апплеток" (applet).
Меня прежде всего интересовали структура языка и архитектура системы. Вчитываясь в документацию, я вдруг осознал, что давно уже в индустрии программного обеспечения мне не доводилось видеть ничего элегантного, продуманного снизу доверху. Основой для языка Java был выбран Си++, и авторы, как говорят они сами, постарались быть ближе к Си++ насколько это возможно, исключив из него редко используемые» малопонятные конструкции. Хотя Java гораздо проще Си++, все-таки это довольно обширный язык, и на полный его обзор ушло бы очень много места Расскажу только о тех его чертах, которые мне больше всего понравились и которые в Си++ реализованы по-другому или не имеют аналогов.
Система Java
Язык Java – это центральная часть целой системы, еще одна важнейшая составная часть которой – виртуальная машина, снабженная своей системой команд. Компилятор переводит текст на языке Java в так называемый байт-код, который затем интерпретируется виртуальной машиной. Таким образом, любое Java-приложение можно исполнить на любом компьютере, где есть интерпретатор системы команд виртуальной машины. В частности, представляет особый интерес использование интерпретатора в составе навигатора WWW.
В процессе разбора команд HTML-файла на очередном Web-cepвepe такой навигатор может наткнуться специальный тег, указывающий файл, содержащий байт-код Java-an-плетки. Тогда файл с байт-кодом переписывается с удаленного компьютера на компьютер пользователя, а затем выполняется Java-интерпретатором. Апплетки могут создавать живую иллюстрацию: в рекламный документ по языку Java включены, например, три апплетки, наглядно демонстрирующие скорость работы трех разных алгоритмов сортировки -очень занимательное зрелище.
Кроме апплеток, которые могут выполнять иллюстративную роль в WWW-документе, на языке Java можно создавать программы для просмотра определенного рода информации (content handler), например, фрактально сжатых изображений. Если навигатор снабжен Java-интерпретатором, а формат файла ему совершенно незнаком, то он попытается найти нужный content handler сначала на локальной машине, потом на удаленной, и если поиск пройдет успешно, то содержимое файла будет изображено корректно.
Еще один тип программ на языке Java – менеджеры протоколов (protocol handler). Сейчас, в связи с распространением коммерции в Internet, для лучшей защиты передаваемых по сети данных многие фирмы создают собственные уникальные навигаторы со встроенной поддержкой нестандартных протоколов. Многим системным администраторам из-за этого приходится содержать до 80 различных навигаторов, "понимающих" всевозможные корпоративные протоколы. Java может значительно упростить работу с ними: теперь достаточно писать менеджер протокола, и все навигаторы, снабженные интерпретатором Java, смогут передавать данные с помощью протокола.
Можно себе представить облегчение программистов в корпорациях, осуществляющих торговлю через Internet, – вместо очередного развесистого браузера теперь достаточно написать всего лишь менеджер протокола на простом изящном языке. При том, что этот язык снабжен и необходимыми инструментами, и развитой библиотекой классов, и поставляется бесплатно.
Авторы языка Java замахнулись на главный источник самых запутанных ошибок в Си и Си++ – работу с динамической памятью и указателями. В языке Java с программиста снимается забота об освобождении заказанной памяти: в систему встроен механизм автоматического "сбора мусора". В спецификации языка сказано, что существование объектов гарантируется до тех пор, пока на объект существует хотя бы одна ссылка; память, занятая объектом, на который нет ни одной ссылки, автоматически освобождается. Очевидно, что авторам было бы не под силу создать подобный механизм при наличии такой же вакханалии указателей, как в Си и Си++.
И действительно, Java запрещает арифметические операции над указателями и преобразование целого типа в указатель и наоборот. Вообще, особый тип данных "указатель" попросту отсутствует, хотя все массивы и все экземпляры классов динамически, и создаются они обязательно с помощью вызова оператора "new".

Элементы массива пронумерованы с нуля. Корректность индексации массива проверяется во время исполнения программы, и если произошел выход за границы – возбуждается исключение. С точки зрения языка Java, массивы – это объекты предопределенного класса с единственным методом length, служащим для определения длины:

Кроме предотвращения чисто программистских ошибок организация работы с динамической памятью в системе Java призвана помочь в решении проблемы безопасности. Согласитесь, гораздо труднее "залезть" в недозволенную область памяти, если в языке вообще нет никаких средств адресной арифметики. Так что вирусы, написанные на языке Java, появятся только после того, как кто-нибудь создаст специальный "вирусо-ориентированный" компилятор, который к тому же сможет порождать байт-код, способный преодолеть контрольные механизмы Java-интерпретатора. Поскольку авторы говорят о непробиваемости многоуровневой защиты системы Java, то с учетом творческого потенциала хакеров год-полтора точно можно жить спокойно и не бояться подцепить вирус через Internet, исполнив какую-нибудь симпатичную апплетку.
Наследование. Интерфейсы
В языке Java нет перекрестного (множественного) наследования. Хотя этот механизм полезен во многих случаях, все-таки его появление в Си++ породило больше проблем, чем решений.
Объявление класса, который выводится из другого класса, на языке Java выглядит, с моей точки зрения, более наглядно, чем в Си++:

В качестве упрощенного аналога перекрестного наследования Java предлагает механизм интерфейсов, заимствованный из языка Objective С. По правилам языка Java переменные, объявленные в интерфейсе, являются статическими, должны быть инициализированы и не могут изменять значение, т.е. по сути являются константами. Описание интерфейса похоже на описание класса – это совокупность объявлений переменных и методов, но, в отличие от классов, методы интерфейсов не имеют определения:

Определения методов, объявленных в интерфейсе, могут появляться только в классах, которые этот интерфейс реализуют:

Интерфейсы можно комбинировать, например:

Интерфейсы можно использовать в качестве типов переменных или параметров:

В этом случае значением такой переменной или параметра может быть
экземпляр любого класса, реализующего указанный интерфейс. Очевидно, что с помощью аппарата интерфейсов можно легко реализовать все то, для чего во многих библиотеках на Си++ (например Borland OWL) используется перекрестное наследование.
Нити. Синхронизация
Создатели языка Java с самого начала предусматривали, что на нем можно будет писать параллельные (multithreaded) программы. Для этого в язык встроены средства синхронизации, и, кроме того, реализован стандартный класс java.lang.Thread, позволяющий порождать нити и управлять ими.
Кактолько появляется параллельность, сразу возникает проблема одновременного доступа к одним и тем же данным. Например, на каком-то участке программы необходимо быть уверенным в том, что используемые здесь переменные не будут изменены какой-нибудь другой нитью – аналогичные проблемы возникают, когда с одной и той же базой данных работает сразу несколько пользователей.
Эта трудность преодолевается с помощью одной из двух новых конструкций языка – синхронизированного метода и синхронизированного блока.
Так выглядит определение синхронизированного метода:

Пример использования синхронизированного блока:

Если одна из нитей начала выполнять синхронизированный метод какого-либо объекта, то все другие нити, попытавшиеся выполнить тот же метод того же объекта, будут "подвешены", пока первая нить не закончит выполнение этого метода. Синхронизировать доступ можно либо к классу, либо к экземпляру класса. Статические (static) синхронизированные методы обеспечивают синхронизацию по отношению к классу; методы, не являющиеся статическим, синхронизируют доступ к экземпляру класса.
Нити порождаются с помощью класса java.lang.Thread.
Приведенные ниже примеры иллюстрируют описание класса, вычисляющего простые числа, создание и запуск соответствуюшего объекта:

Класс Thread содержит полный набор инструментов управления нитями: нить можно остановить, "подвесить" на определенное время, уничтожить, изменить приоритет и пр.
Напоследок
В языке Java есть еще очень много интересных особенностей. Например, стандартные классы, реализующие управляющие элементы графического интерфейса (пакет awt), пакеты, содержащие реализации сетевых протоколов ftp, nntp, http. Всего просто не перечислишь. А сейчас на сервере фирмы Sun (http://java.sun.com) уже доступна версия 1.0 комплекта разработчика JDK(Java Development Kit), и, перекачав каких-то 3,7 мегабайта, можно начинать писать свой собственный навигатор.