Глава 1. Введение
Содержание
Язык программирования Java® — это универсальный, конкурентный, основанный на классах, объектно-ориентированный язык. Он разработан таким образом, чтобы многие программисты могли легко освоить его. Язык программирования Java связан с C и C++, но организован несколько иначе, с исключением ряда аспектов C и C++ и включением нескольких идей из других языков. Он предназначен для использования в производстве, а не в исследовательских целях, и поэтому, как предложил К. А. Р. Хоар в своей классической статье по проектированию языков, при разработке было избегано включение новых и не проверенных функций.
Язык программирования Java — это язык со строгой и статической типизацией. В этой спецификации чётко различаются ошибки, которые могут и должны быть обнаружены на этапе компиляции, и те, которые возникают во время выполнения. Этап компиляции обычно включает в себя трансляцию программ в машинонезависимый формат байт-кода. Действия во время выполнения включают в себя загрузку и связывание классов, необходимых для выполнения программы, необязательную генерацию машинного кода и динамическую оптимизацию программы, а также фактическое выполнение программы.
Язык программирования Java — это язык относительно высокого уровня, в котором детали машинного представления недоступны через язык. Он включает автоматическое управление памятью, как правило, с использованием сборщика мусора, для избежания проблем безопасности явного удаления (как в C's free или C++'s delete). Высокопроизводительные реализации с сборщиком мусора могут иметь ограниченные паузы для поддержки системного программирования и приложений реального времени. Язык не содержит небезопасных конструкций, таких как доступ к массивам без проверки индексов, так как такие небезопасные конструкции могут привести к непредсказуемому поведению программы.
Язык программирования Java обычно компилируется в набор команд и двоичный формат байт-кода, определённые в спецификации виртуальной машины Java, Java SE 21 Edition.
В главе 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, издание Java SE 21 через перекрёстные ссылки вида (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 для получения отзывов разработчиков на основе реального использования; это может привести к её постоянному включению в будущие версии платформы Java SE.
Реализации должны отключить, как во время компиляции, так и во время выполнения, превью-функции, определённые данной версией платформы Java SE, если пользователь не укажет через систему, как во время компиляции, так и во время выполнения, что превью-функции должны быть включены.
Превью-функции, определённые данной версией платформы Java SE, перечислены в Спецификации платформы Java SE для этой версии. Превью-функции специфицируются следующим образом:
-
Превью-функции языка специфицируются в самостоятельных документах, которые указывают изменения («различия») в Спецификации языка Java® для этой версии. Спецификации превью-функций языка интегрируются в Спецификацию языка Java® путем ссылки и становятся её частью, если и только если превью-функции включены во время компиляции.
Java SE 21 определяет три превью-функции языка: Шаблоны строк, Безымянные шаблоны и переменные и Безымянные классы и методы экземпляра
main. Самостоятельные документы, которые специфицируют эти превью-функции, доступны на веб-сайте Oracle, на котором размещена Спецификация языка Java®:https://docs.oracle.com/javase/specs/. -
Превью-API специфицируются в Спецификации API Java SE для этой версии.
Правила использования превью-функций языка следующие:
-
Если превью-функции отключены, любая ссылка в исходном коде на превью-функцию языка или на класс или интерфейс, объявленный с использованием превью-функции языка, приводит к ошибке компиляции.
-
Если превью-функции включены, любая ссылка в исходном коде на класс или интерфейс, объявленный с использованием превью-функции языка, приводит к предупреждению превью, если не выполняется одно из следующих условий:
Когда превью-функции включены, компиляторы Java настоятельно рекомендуют выводить предупреждение для каждой ссылки в исходном коде на превью-функцию языка. Подробности этого предупреждения выходят за рамки этой спецификации, но целью должно быть предупреждение программистов о возможности того, что код может быть затронут будущими изменениями превью-функций языка.
Некоторые превью-API описываются как рефлексивные в Спецификации платформы Java SE, главным образом в пакетах java.lang.reflect, java.lang.invoke и javax.lang.model. Правило использования рефлексивных превью-API следующее:
-
Включены ли превью-функции или нет, любая ссылка в исходном коде на элемент рефлексивного превью-API приводит к предупреждению превью, если не выполняется одно из следующих условий:
-
Объявление, где появляется ссылка, находится в одном модуле с объявлением элемента рефлексивного превью-API.
-
Ссылка появляется в объявлении, снабжённом аннотацией для подавления предупреждений превью.
-
Ссылка появляется в объявлении импорта.
-
Все превью-API, не описанные как рефлексивные в Спецификации платформы Java SE, являются обычными. Правила использования обычных превью-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, документ 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., и Dennis M. Ritchie. Язык программирования C, 2-е изд. Prentice Hall, Энглвуд Клифс, Нью-Джерси, 1988, ISBN 0-13-110362-8.
Madsen, Ole Lehrmann, Birger Møller-Pedersen и Kristen Nygaard. Объектно-ориентированное программирование на языке программирования Beta. Addison-Wesley, Ридинг, Массачусетс, 1993, ISBN 0-201-62430-3.
Mitchell, James G., William Maybury и Richard Sweet. Язык программирования Mesa, версия 5.0. Xerox PARC, Пало-Альто, Калифорния, CSL 79-3, апрель 1979 г.
Stroustrup, Bjarne. Язык программирования C++, 2-е изд. Addison-Wesley, Ридинг, Массачусетс, 1991, перепечатано с исправлениями в январе 1994 г., ISBN 0-201-53992-6.
Консорциум Unicode. Стандарт Unicode, версия 15.0. Маунтин-Вью, Калифорния, 2022 г., ISBN 978-1-936213-32-0.
© Oracle and/or its affiliates. All rights reserved.
Licensed under the Oracle Technology Network License Agreement.