Глава 1. Введение
Оглавление
Язык программирования Java® — это универсальный, конкурентный, основанный на классах, объектно-ориентированный язык. Он разработан таким образом, чтобы быть достаточно простым для освоения многими программистами. Язык программирования Java связан с C и C++, но организован несколько иначе, с исключением ряда аспектов C и C++ и включением нескольких идей из других языков. Он предназначен для использования в производстве, а не в исследовательских целях, и, как предложил К. А. Р. Хоар в своей классической статье по проектированию языка, при разработке было избегано включение новых и непроверенных функций.
Язык программирования Java имеет сильную и статическую типизацию. Данная спецификация чётко различает ошибки времени компиляции, которые могут и должны быть обнаружены на стадии компиляции, и ошибки, возникающие во время выполнения. Компиляция обычно включает перевод программ в независимую от машины байтовую кодовую форму. Действия во время выполнения включают загрузку и связывание необходимых классов для выполнения программы, необязательное создание машинного кода и динамическую оптимизацию программы, а также фактическое выполнение программы.
Язык программирования Java — это язык относительно высокого уровня, так как детали машинного представления недоступны через сам язык. Он включает автоматическое управление памятью, как правило, с использованием сборщика мусора, чтобы избежать проблем безопасности явного освобождения (как в C's free или C++'s delete). Высокопроизводительные реализации с сборщиком мусора могут иметь ограниченные паузы для поддержки системного программирования и приложений реального времени. Язык не включает никаких небезопасных конструкций, таких как доступ к массивам без проверки индекса, так как такие небезопасные конструкции могут привести к непредсказуемому поведению программы.
Язык программирования Java обычно компилируется в набор инструкций байткода и двоичный формат, определённый в Спецификации виртуальной машины Java, Java SE 24 издание.
В главе 2 описываются грамматики и обозначения, используемые для представления лексических и синтаксических грамматик языка.
Глава 3 описывает лексическую структуру языка программирования Java, которая основана на C и C++. Язык написан в наборе символов Unicode. Он поддерживает написание символов Unicode на системах, которые поддерживают только ASCII.
Глава 4 описывает типы, значения и переменные. Типы подразделяются на примитивные типы и ссылочные типы.
Примитивные типы определяются одинаково на всех машинах и во всех реализациях и представляют собой целые числа со знаком в дополнительном коде, числа с плавающей точкой IEEE 754, тип boolean и тип символа Unicode char. Значения примитивных типов не разделяют состояние.
Ссылочные типы – это типы классов, типы интерфейсов и типы массивов. Ссылочные типы реализуются динамически создаваемыми объектами, которые являются экземплярами классов или массивов. Может существовать множество ссылок на каждый объект. Все объекты (включая массивы) поддерживают методы класса Object, который является (единственным) корнем иерархии классов. Предопределенный класс String поддерживает строки символов Unicode. Существуют классы для обертывания примитивных значений внутри объектов. Во многих случаях обертывание и распаковку выполняет компилятор (в этом случае, обертывание называется боксер, а распаковка – унбоксинг). Классы и интерфейсы могут быть обобщенными, то есть могут быть параметризованы ссылочными типами. Параметризованные типы таких классов и интерфейсов могут затем вызываться со специфическими аргументами типа.
Переменные – это типизированные места хранения. Переменная примитивного типа хранит значение этого примитивного типа. Переменная типа класса может содержать нулевую ссылку или ссылку на объект, который является экземпляром указанного класса или любого подкласса этого класса. Переменная типа интерфейса может содержать нулевую ссылку или ссылку на экземпляр любого класса, реализующего указанный интерфейс. Переменная типа массива может содержать нулевую ссылку или ссылку на массив. Переменная типа класса Object может содержать нулевую ссылку или ссылку на любой объект, будь то экземпляр класса или массив.
Глава 5 описывает преобразования и числовые повышения. Преобразования изменяют тип выражения в момент компиляции и, иногда, значение выражения. Эти преобразования включают преобразования боксер и унбоксинг между примитивными и ссылочными типами. Числовые повышения используются для преобразования операндов числового оператора в общий тип, где может быть выполнена операция. В языке нет лазеек; преобразования ссылочных типов проверяются во время выполнения для обеспечения безопасности типов.
Глава 6 описывает объявления и имена, а также то, как определить, что означают имена (то есть, какое объявление обозначает имя). Язык программирования Java не требует, чтобы классы и интерфейсы или их члены были объявлены перед их использованием. Порядок объявления важен только для локальных переменных, локальных классов, локальных интерфейсов и порядка инициализаторов полей в классе или интерфейсе. Здесь описаны рекомендуемые соглашения об именовании, которые делают программы более читабельными.
Глава 7 описывает структуру программы, которая организована в пакеты. Члены пакета – это классы, интерфейсы и подпакеты. У пакетов и, следовательно, их членов, есть имена в иерархическом пространстве имен; система доменных имен Интернета обычно может использоваться для формирования уникальных имен пакетов. Единицы компиляции содержат объявления классов и интерфейсов, которые являются членами данного пакета, и могут импортировать классы и интерфейсы из других пакетов, чтобы дать им короткие имена.
Пакеты могут быть сгруппированы в модули, которые служат строительными блоками при создании очень больших программ. Объявление модуля указывает, какие другие модули (и, следовательно, пакеты, а следовательно, классы и интерфейсы) необходимы для компиляции и выполнения кода в собственных пакетах.
Язык программирования Java поддерживает ограничения на внешний доступ к членам пакетов, классов и интерфейсов. Члены пакета могут быть доступны только другим членам того же пакета или членам других пакетов того же модуля или членам пакетов в других модулях. Аналогичные ограничения применяются к членам классов и интерфейсов.
Глава 8 описывает классы. Членами классов являются классы, интерфейсы, поля (переменные) и методы. Классовые переменные существуют один раз на класс. Методы класса работают без ссылки на конкретный объект. Экземплярные переменные динамически создаются в объектах, являющихся экземплярами классов. Экземплярные методы вызываются на экземплярах классов; такие экземпляры становятся текущим объектом this во время их выполнения, поддерживая стиль объектно-ориентированного программирования.
Классы поддерживают одиночное наследование, в котором каждый класс имеет единственный суперкласс. Каждый класс наследует члены от своего суперкласса и, в конечном счете, от класса Object. Переменные типа класса могут ссылаться на экземпляр указанного класса или любого подкласса этого класса, что позволяет использовать новые классы с существующими методами полиморфно.
Классы поддерживают конкурентное программирование с методами synchronized. Методы объявляют проверяемые исключения, которые могут возникнуть при их выполнении, что позволяет проверять во время компиляции, чтобы убедиться, что исключительные ситуации обрабатываются. Объекты могут объявлять метод finalize, который будет вызываться перед тем, как объекты будут удалены сборщиком мусора, что позволит объектам очистить свое состояние.
Для простоты язык не имеет разделенных на части объявления "заголовков" и реализации класса, а также разделенных типов и иерархий классов.
Ограниченный тип класса, классы перечислений, поддерживает определение небольших наборов значений и их манипулирование безопасным для типа способом. В отличие от перечислений в других языках, константы перечисления являются объектами и могут иметь свои собственные методы.
Еще один ограниченный тип класса, классы записей, поддерживает компактное выражение простых объектов, которые служат агрегатами значений.
Глава 9 описывает интерфейсы. Членами интерфейсов являются классы, интерфейсы, константные поля и методы. Классы, которые в противном случае не связаны, могут реализовывать один и тот же интерфейс. Переменная типа интерфейса может содержать ссылку на любой объект, реализующий интерфейс.
Классы и интерфейсы поддерживают множественное наследование от интерфейсов. Класс, реализующий один или несколько интерфейсов, может наследовать экземплярные методы как от своего суперкласса, так и от своих суперинтерфейсов.
Аннотации являются метаданными, которые могут применяться к объявлениям в программе, а также к использованию типов в объявлениях и выражениях. Форма аннотации определяется интерфейсом аннотации, специализированным типом интерфейса. Аннотации не могут каким-либо образом влиять на семантику программ на языке программирования Java. Однако они предоставляют полезный ввод для различных инструментов.
Глава 10 описывает массивы. Доступ к массивам включает проверку границ. Массивы являются динамически создаваемыми объектами и могут быть присвоены переменным типа Object. Язык поддерживает массивы массивов, а не многомерные массивы.
Глава 11 описывает исключения, которые не возобновляются и полностью интегрированы в семантику языка и механизмы параллельности. Существует три типа исключений: проверяемые исключения, исключения времени выполнения и ошибки. Компилятор гарантирует, что проверяемые исключения обрабатываются должным образом, требуя, чтобы метод или конструктор мог привести к проверяемому исключению только в том случае, если метод или конструктор его объявляет. Это обеспечивает проверку во время компиляции наличия обработчиков исключений и помогает программировать большие программы. Большинство определяемых пользователем исключений должны быть проверяемыми исключениями. Недопустимые операции в программе, обнаруженные виртуальной машиной Java, приводят к исключениям времени выполнения, таким как NullPointerException. Ошибки возникают из-за сбоев, обнаруженных виртуальной машиной Java, таких как OutOfMemoryError. Большинство простых программ не пытаются обработать ошибки.
Глава 12 описывает действия, происходящие во время выполнения программы. Программа обычно хранится в виде бинарных файлов, представляющих скомпилированные классы и интерфейсы. Эти бинарные файлы могут загружаться в виртуальную машину Java, связываться с другими классами и интерфейсами и инициализироваться.
После инициализации можно использовать методы и переменные класса. Некоторые классы могут быть созданы для создания новых объектов типа класса. Объекты, являющиеся экземплярами класса, также содержат экземпляр каждого суперкласса класса, а создание объекта включает рекурсивное создание этих экземпляров суперклассов.
Когда на объект больше нет ссылок, он может быть возвращён сборщиком мусора. Если объект объявляет финализатор, финализатор выполняется до того, как объект будет возвращён, чтобы дать объекту последний шанс очистить ресурсы, которые в противном случае не были бы освобождены. Когда класс больше не нужен, он может быть загружен.
Глава 13 описывает бинарную совместимость, определяя влияние изменений в классах и интерфейсах на другие классы и интерфейсы, использующие изменённые классы и интерфейсы, но не перекомпилированные. Эти соображения представляют интерес для разработчиков классов и интерфейсов, которые должны широко распространяться, в непрерывной серии версий, часто через Интернет. Хорошие среды разработки программ автоматически перекомпилируют зависимый код всякий раз, когда класс или интерфейс изменяется, поэтому большинство программистов не должны беспокоиться об этих деталях.
Глава 14 описывает блоки и операторы, основанные на C и C++. В языке нет оператора goto, но есть помеченные break и continue операторы. В отличие от C, язык программирования Java требует boolean (или Boolean) выражений в операторах управления потоком и не преобразует типы в boolean неявно (за исключением унбоксинга), с надеждой поймать больше ошибок во время компиляции. Оператор synchronized обеспечивает базовый мониторинг блокировки на уровне объектов. Оператор try может включать клаузы catch и finally для защиты от нелокальных передач управления. Глава 14 также описывает шаблоны, которые используются внутри операторов (и выражений) для условного объявления и инициализации локальных переменных.
Глава 15 описывает выражения. В этом документе полностью определен (явный) порядок оценки выражений для повышения детерминизма и портативности. Перегруженные методы и конструкторы разрешаются во время компиляции, выбирая наиболее специфический метод или конструктор из тех, которые применимы.
Глава 16 описывает точный способ, которым язык гарантирует, что локальные переменные определены до использования. Хотя все остальные переменные автоматически инициализируются по умолчанию, язык программирования Java не инициализирует автоматически локальные переменные, чтобы избежать маскирования ошибок программирования.
Глава 17 описывает семантику потоков и блокировок, которые основаны на основанной на мониторах конкуренции, первоначально представленной в языке программирования Mesa. Язык программирования Java определяет модель памяти для многопроцессорных систем с общей памятью, которая поддерживает реализации с высокой производительностью.
Глава 18 описывает различные алгоритмы вывода типов, используемые для проверки применимости обобщенных методов и вывода типов в вызове обобщенного метода.
Глава 19 представляет синтаксическую грамматику языка.
Большинство примеров программ, приведенных в тексте, готовы к выполнению и имеют похожую форму:
class Test {
public static void main(String[] args) {
for (int i = 0; i < args.length; i++)
System.out.print(i == 0 ? args[i] : " " + args[i]);
System.out.println();
}
}
На машине с установленным Oracle JDK этот класс, сохраненный в файле Test.java, можно скомпилировать и выполнить, выполнив команды:
javac Test.java java Test Hello, world.
что приведет к выводу:
Hello, world.
В этом документе мы ссылаемся на классы и интерфейсы, взятые из API платформы Java SE. Всякий раз, когда мы ссылаемся на класс или интерфейс (кроме тех, которые объявлены в примере) с помощью одного идентификатора N, предполагается ссылка на класс или интерфейс с именем N в пакете java.lang. Мы используем каноническое имя (§6.7) для классов или интерфейсов из пакетов, отличных от java.lang.
Внутри этого документа перекрестная ссылка отображается как (§x.y). Иногда мы ссылаемся на понятия в Спецификации Java Virtual Machine, издание Java SE 24 с помощью перекрестных ссылок в формате (JVMS §x.y).
Ненормативный текст, предназначенный для уточнения нормативного текста этого документа, представлен меньшим, отступающим текстом.
Это ненормативный текст. Он предоставляет интуицию, обоснование, советы, примеры и т. д.
Для сокращения описания некоторых правил, особенно тех, которые систематически анализируют конструкции языка программирования Java, используется сокращение «iff», означающее «если и только если».
Система типов языка программирования Java иногда опирается на понятие подстановки. Запись [F1:=T1,...,Fn:=Tn] обозначает подстановку Fi на Ti для 1 ≤ i ≤ n.
Как отмечалось выше, этот документ часто ссылается на классы и интерфейсы API платформы Java SE. В частности, некоторые классы и интерфейсы имеют особую связь с языком программирования Java. Примеры включают такие классы, как Object, Class, ClassLoader, String и Thread, а также классы и интерфейсы в пакете java.lang.reflect, среди прочих. Этот документ ограничивает поведение таких классов и интерфейсов, но не предоставляет полную спецификацию для них. Читатель может обратиться к документации API платформы Java SE.
Следовательно, в этом документе не описывается рефлексия подробно. Многие языковые конструкции имеют аналоги в Core Reflection API (java.lang.reflect) и Language Model API (javax.lang.model), но они обычно не обсуждаются здесь. Например, когда мы перечисляем способы создания объекта, мы обычно не включаем способы, которыми это может быть сделано с помощью Core Reflection API. Читатели должны быть осведомлены об этих дополнительных механизмах, даже если они не упоминаются в тексте.
Предварительная функция — это:
-
новая функция языка программирования Java («предварительная функция языка»), или
-
новый модуль, пакет, класс, интерфейс, поле, метод, конструктор или константа перечисления в пространстве имён
java.*илиjavax.*(«предварительный API»)
которая полностью определена, полностью реализована и всё же не постоянна. Она доступна в реализациях данной версии Java SE Platform для получения отзывов разработчиков на основе реального использования; это может привести к её постоянному использованию в будущих версиях Java SE Platform.
Реализации должны отключать предварительные функции, определённые данной версией Java SE Platform, как во время компиляции, так и во время выполнения, если пользователь не укажет в системе хоста, как во время компиляции, так и во время выполнения, что предварительные функции должны быть включены.
Предварительные функции, определённые данной версией Java SE Platform, перечислены в Спецификации Java SE Platform для этой версии. Предварительные функции определяются следующим образом:
-
Предварительные функции языка определяются в автономных документах, которые указывают изменения («различия») в Спецификации языка Java® для этой версии. Спецификации предварительных функций языка включаются в Спецификацию языка Java® по ссылке и становятся её частью, только если предварительные функции включены во время компиляции.
Java SE 24 определяет четыре предварительные функции языка: Гибкие тела конструкторов; Простые исходные файлы и методы экземпляра
main; Декларации импорта модуля; и Примитивные типы в шаблонах,instanceofиswitch. Автономные документы, которые определяют эти предварительные функции, доступны на веб-сайте, на котором размещена эта версия Спецификации языка Java®. -
Предварительные API определяются в Спецификации API Java SE для этой версии.
Правила использования предварительных функций языка следующие:
-
Если предварительные функции отключены, ссылка на предварительную функцию языка или на класс или интерфейс, объявленный с помощью предварительной функции языка, приводит к ошибке компиляции.
-
Если предварительные функции включены, ссылка на класс или интерфейс, объявленный с помощью предварительной функции языка, приводит к предупреждению о предварительном режиме, если не выполняется одно из следующих условий:
Когда предварительные функции включены, Java-компиляторы настоятельно рекомендуются выдавать неподдающееся подавлению предупреждение для каждой ссылки в исходном коде на предварительную функцию языка. Подробности об этом предупреждении выходят за рамки этой спецификации, но целью должно быть предупреждение программистов о возможности влияния будущих изменений предварительных функций языка на код.
Некоторые предварительные API описаны как рефлексивные в Спецификации Java SE Platform, главным образом в пакетах java.lang.reflect, java.lang.invoke и javax.lang.model. Правило использования рефлексивных предварительных API следующее:
-
В независимости от того, включены ли предварительные функции или нет, любая ссылка в исходном коде на элемент рефлексивного предварительного API вызывает предупреждение о предварительном режиме, если не выполняется одно из следующих условий:
-
Объявление, где появляется ссылка, находится в том же модуле, что и объявление элемента рефлексивного предварительного API.
-
Ссылка появляется в объявлении, которое помечено аннотацией для подавления предупреждений о предварительном режиме.
-
Ссылка появляется в декларации импорта.
-
Все предварительные API, не описанные как рефлексивные в Спецификации Java SE Platform, являются обычными. Правила использования обычных предварительных API следующие:
-
Если предварительные функции отключены, ссылка на элемент обычного предварительного API вызывает ошибку компиляции, если:
-
Объявление, где появляется ссылка, находится в том же модуле, что и объявление элемента обычного предварительного API.
-
-
Если предварительные функции включены, ссылка на элемент обычного предварительного API вызывает предупреждение о предварительном режиме, если не выполняется одно из следующих условий:
-
Объявление, где появляется ссылка, находится в том же модуле, что и объявление элемента обычного предварительного API.
-
Ссылка появляется в объявлении, которое помечено аннотацией для подавления предупреждений о предварительном режиме.
-
Ссылка появляется в декларации импорта.
-
Читатели могут сообщать об технических ошибках и неоднозначностях в Спецификации языка Java® в jls-jvms-spec-comments@openjdk.org.
Вопросы, касающиеся поведения javac (компилятора ссылок для языка программирования Java), и, в частности, его соответствия этой спецификации, можно отправлять в compiler-dev@openjdk.org.
Библиография
Apple Computer. Руководство по Dylan. Apple Computer Inc., Купертино, Калифорния. 29 сентября 1995 г.
Bobrow, Daniel G., Linda G. DeMichiel, Richard P. Gabriel, Sonya E. Keene, Gregor Kiczales и David A. Moon. Спецификация Common Lisp Object System, документ X3J13 88-002R, июнь 1988; появляется как глава 28 в Steele, Guy. Common Lisp: Язык, 2-е изд. Digital Press, 1990, ISBN 1-55558-041-6, 770-864.
Ellis, Margaret A., и Bjarne Stroustrup. Комментированное руководство по C++. Addison-Wesley, Ридинг, Массачусетс, 1990, переиздано с исправлениями в октябре 1992 г., ISBN 0-201-51459-1.
Goldberg, Adele и Robson, David. Smalltalk-80: Язык. Addison-Wesley, Ридинг, Массачусетс, 1989, ISBN 0-201-13688-0.
Harbison, Samuel. Modula-3. Prentice Hall, Энглвуд Клифс, Нью-Джерси, 1992, ISBN 0-13-596396.
Hoare, C. A. R. Рекомендации по проектированию языков программирования. Технический отчёт кафедры компьютерных наук Стэнфордского университета № CS-73-403, декабрь 1973 г. Перепечатано в симпозиуме SIGACT/SIGPLAN по принципам языков программирования. Ассоциация вычислительной техники, Нью-Йорк, октябрь 1973 г.
IEEE. Стандарт IEEE для вычислений с плавающей запятой. IEEE Std 754-2019 (переработка IEEE 754-2008). Июль 2019 г., ISBN 978-1-5044-5924-2.
Kernighan, Brian W., и Ritchie, Dennis M. Язык программирования C, 2-е изд. Prentice Hall, Энглвуд Клифс, Нью-Джерси, 1988, ISBN 0-13-110362-8.
Madsen, Ole Lehrmann, Møller-Pedersen, Birger и Nygaard, Kristen. Объектно-ориентированное программирование на языке программирования Beta. Addison-Wesley, Ридинг, Массачусетс, 1993, ISBN 0-201-62430-3.
Mitchell, James G., Maybury, William и Sweet, Richard. Язык программирования Mesa, версия 5.0. Xerox PARC, Пало-Альто, Калифорния, CSL 79-3, апрель 1979 г.
Stroustrup, Bjarne. Язык программирования C++, 2-е изд. Addison-Wesley, Ридинг, Массачусетс, 1991, переиздано с исправлениями в январе 1994 г., ISBN 0-201-53992-6.
Консорциум Unicode. Стандарт Unicode, версия 16.0.0. Южный Сан-Франциско: Консорциум Unicode, 2024. ISBN 978-1-936213-34-4.
© Oracle and/or its affiliates. All rights reserved.
Licensed under the Oracle Technology Network License Agreement.