Spec-Zone .ru
спецификации, руководства, описания, API
|
Содержание | Предыдущий | Следующий | Индекс | JavaTM Машинная Спецификация TMVirtual |
ГЛАВА 2
Виртуальная машина Java была разработана, чтобы поддерживать язык программирования Java. Некоторые понятия и словарь от языка программирования Java таким образом полезны, пытаясь понять виртуальную машину. Эта глава дает краткий обзор, предназначенный, чтобы поддерживать спецификацию виртуальной машины Java, но не является самостоятельно частью той спецификации.
Контент этой главы был сжат из первого выпуска Спецификации языка JavaTM, Джеймсом Гослингом, Биллом Джоем, и Читателями Гая Стиле.1, знакомыми с языком программирования Java, но не со Спецификацией языка JavaTM, должен, по крайней мере, просмотреть эту главу для терминологии, которую это представляет. Любые несоответствия между этой главой и Спецификацией языка JavaTM должны быть разрешены в пользу Спецификации языка JavaTM.
Эта глава не пытается обеспечить введение в язык программирования Java. Для такого введения см. Язык программирования JavaTM, Второй Выпуск, Кеном Арнольдом и Джеймсом Гослингом.
http:// www.unicode.org
. Программы, записанные в языке программирования Java используемая версия 2.0.14 Стандарта Unicode в JDK, выпускают 1.1 до 1.1.6 и используемая версия 1.1.5 Стандарта Unicode в выпуске 1.0 JDK. За исключением комментариев, идентификаторы (§2.2), и содержание символьных и строковых литералов (§2.3), все входные элементы в программе, записанной в языке программирования Java, формируются из только символов ASCII. ASCII (ANSI X3.4) является Стандартный американский код обмена информацией. Первые 128 символов кодировки символов Unicode являются символами ASCII.
Метод (§2.10) Character.isJavaLetter
возвраты true
когда передано символ Unicode, который, как полагают, является буквой в идентификаторе. Метод Character.isJavaLetterOrDigit
возвраты true
когда передано символ Unicode, который, как полагают, является буквой или цифрой в идентификаторе.
Два идентификатора являются тем же самым, только если у них есть тот же самый символ Unicode для каждой буквы или цифры; идентификаторы, у которых есть то же самое внешнее появление, могут все еще отличаться. Идентификатор не должен быть тем же самым как булевым литералом (§2.3), нулевой литерал (§2.3), или ключевое слово в языке программирования Java.
String
введите (§2.4.8), или нулевой тип (§2.4). Строковые литералы и, более широко, строки, которые являются значениями константных выражений, "интернируются", чтобы совместно использовать уникальные экземпляры, используя метод String.intern
. У нулевого типа есть одно значение, нулевая ссылка, обозначенная литералом null
. boolean
у типа есть два значения, обозначенные литералами true
и false
.
Типы языка программирования Java делятся на две категории: типы примитивов (§2.4.1) и ссылочные типы (§2.4.6). Есть также специальный нулевой тип, тип выражения null
, у которого нет никакого имени. Нулевая ссылка является единственным возможным значением выражения нулевого типа и может всегда преобразовываться в любой ссылочный тип. Практически, программист может проигнорировать нулевой тип и только симулировать это null
специальный литерал, который может иметь любой ссылочный тип.
Соответствуя типам примитивов и ссылочным типам, есть две категории значений данных, которые могут быть сохранены в переменных, передали как параметры, возвращенные методами, и работали на: примитивные значения (§2.4.1) и ссылочные значения (§2.4.6).
Типы примитивов boolean
введите и числовые типы. Числовые типы являются целочисленными типами и типами с плавающей точкой.
Целочисленные типы byte
, short
, int
, и long
, чьи значения являются 8-разрядными, 16-разрядными, 32-разрядными, и 64-разрядными two's-дополнительными целыми числами со знаком, соответственно, и char
, чьи значения являются 16-разрядными целыми без знака, представляющими символы Unicode (§2.1).
Типы с плавающей точкой float
и double
, которые концептуально связываются с 32-разрядной одинарной точностью и 64-разрядными значениями IEEE 754 двойной точности и операциями как определено в Стандарте IEEE для Двоичной Арифметики С плавающей точкой, Стандарт ANSI/IEEE 754-1985 (IEEE, Нью-Йорк).
boolean
у типа есть значения истинности true
и false
.
Операнды определенных унарных операторов и бинарных операторов подвергаются числовому продвижению (§2.6.10).
Встроенные целочисленные операторы не указывают (положительный или отрицательный) на переполнение всегда; они повторяются на переполнении. Единственные целочисленные операторы, которые могут выдать исключение, являются целочисленным дележом и целочисленными операторами остатка, которые могут бросить ArithmeticException
если правый операнд является нулем.
Любое значение любого целочисленного типа может быть брошено к или от любого числового типа. Нет никаких бросков между целочисленными типами и типом boolean
.
Каждая реализация языка программирования Java обязана поддерживать два стандартных набора значений с плавающей точкой, названных набором значений плавающим и двойным набором значений. Кроме того, реализация языка программирования Java может поддерживать или или обе из двух расширенных экспонент наборы значений с плавающей точкой, названные набором значений "расширенная экспонента плавающая" и набор значений "двойная расширенная экспонента". Эти наборы значений расширенной экспоненты, при определенных обстоятельствах, могут использоваться вместо стандартных наборов значений, чтобы представить значения выражений плавания типа или двойной.
Конечные ненулевые значения любого набора значений с плавающей точкой могут все быть выражены в форме s · м. · 2 (e-N + 1), где s +1 или-1, м. является положительным целым числом меньше чем 2N, и e является целым числом между Эмином = - (2 K - 1-2) и Emax = 2 K - 1-1, включительно, и где N и K являются параметрами, которые зависят от набора значений. Некоторые значения могут быть представлены в этой форме больше чем одним способом; например, если значение v в наборе значений могло бы быть представлено в этой форме, используя определенные значения для s, м., и e, затем если бы это произошло, которым м. был даже, и e составлял меньше чем 2 k-1, то можно было разделить на два м. и увеличить e на 1, чтобы произвести второе представление для того же самого значения v. Представление в этой форме вызывают нормализованное если м. 2N-1; иначе представление, как говорят, денормализовывается. Если значение в наборе значений не может быть представлено таким способом, которым м. 2N-1, то значение, как говорят, является денормализованным значением, потому что у этого нет никакого нормализованного представления.
Ограничения на параметры N и K (и на полученные параметры Эмин и Эмэкс) для этих требуемых двух и два дополнительных набора значений с плавающей точкой получаются в итоге в Таблице 2.1.
Параметр | плавание | "пустите в ход расширенную экспоненту" | двойной | "удвойте расширенную экспоненту" |
---|---|---|---|---|
N | 24 | 24 | 53 | 53 |
K | 8 | 11 | 11 | 15 |
Emax | +127 | +1023 | +1023 | +16383 |
Эмин | -126 | -1022 | -1022 | -16382 |
Где один или оба набора значений расширенной экспоненты поддерживаются реализацией, затем для каждого поддерживаемого набора значений расширенной экспоненты есть определенный зависящий от реализации постоянный K, значение которого ограничивается Таблицей 2.1; это значение K поочередно диктует значения для Эмина и Эмэкса.
Каждый из этих четырех наборов значений включает не только конечные ненулевые значения, которые приписываются ему выше, но также и пять значений положительный нуль, отрицательный нуль, положительная бесконечность, отрицательная бесконечность, и НЭН.
Отметьте, что ограничения в Таблице 2.1 разрабатываются так, чтобы каждый элемент набора значений плавающего был обязательно также элементом набора значений "расширенная экспонента плавающая", двойной набор значений, и набор значений "двойная расширенная экспонента". Аналогично, каждый элемент двойного набора значений является обязательно также элементом набора значений "двойная расширенная экспонента". Каждый набор значений расширенной экспоненты имеет больший диапазон значений экспоненты чем соответствующий стандартный набор значений, но не имеет большей точности.
Элементы набора значений плавающего являются точно значениями, которые могут быть представлены, используя единственный формат с плавающей точкой, определенный в стандарте IEEE 754, за исключением того, что есть только одно значение НЭН (IEEE 754 определяет 224 - 2 отличных значения НЭН). Элементы двойного набора значений являются точно значениями, которые могут быть представлены, используя двойной формат с плавающей точкой, определенный в стандарте IEEE 754, за исключением того, что есть только одно значение НЭН (IEEE 754 определяет 253 - 2 отличных значения НЭН). Отметьте, однако, что элементы "плавания, расширенная экспонента" и наборы значений "двойная расширенная экспонента", определенная здесь, не соответствуют значениям, которые могут быть представлены, используя IEEE 754 единственные расширенные и двойные расширенные форматы, соответственно.
Плавание, "расширенная экспонента плавающая", дважды, и наборы значений "двойная расширенная экспонента" не является типами. Это всегда корректно для реализации языка программирования Java, чтобы использовать элемент набора значений плавающего, чтобы представить значение плавания типа; однако, может быть допустимо в определенных областях кода для реализации использовать элемент набора значений "расширенная экспонента плавающая" вместо этого. Точно так же это всегда корректно для реализации, чтобы использовать элемент двойного набора значений, чтобы представить значение двойного типа; однако, может быть допустимо в определенных областях кода для реализации использовать элемент набора значений "двойная расширенная экспонента" вместо этого.
За исключением НЭН, упорядочиваются значения с плавающей точкой; расположенный от самого маленького до самого большого, они - отрицательная бесконечность, отрицательные конечные ненулевые значения, положительный и отрицательный нуль, положительные конечные ненулевые значения, и положительная бесконечность.
На сравнении положительный нулевой и отрицательный нуль равен; таким образом результатом выражения 0.0 ==-0.0 является истина, и результатом 0.0>-0.0 является ложь. Но другие операции могут отличить положительный и отрицательный нуль; например, у 1.0/0.0 есть значение положительная бесконечность, в то время как значение 1.0/-0.0 является отрицательной бесконечностью.
НЭН неупорядочивают, таким образом, числовые операторы сравнения <<=>, и> = возвращают false, если или или оба операнда НЭН. Оператор равенства == возвращает false, если любым операндом является НЭН, и оператор неравенства! = возвращает true, если любым операндом является НЭН. В частности x! = x является истиной, если и только если x является НЭН, и (x <y) ==! (x> =y), будет ложь, если x или y будет НЭН.
Любое значение типа с плавающей точкой может быть брошено к или от любого числового типа. Нет никаких бросков между типами с плавающей точкой и булевской переменной типа.
Если по крайней мере один из операндов к бинарному оператору имеет тип с плавающей точкой, то работа является работой с плавающей точкой, даже если другой операнд является неотъемлемой частью. Операнды определенных унарных операторов и бинарных операторов подвергаются числовому продвижению (§2.6.10).
Значения, возвращенные операторами на числах с плавающей точкой, являются определенными IEEE 754. В частности язык программирования Java требует поддержки IEEE 754 денормализованные числа с плавающей точкой и постепенная потеря значимости, которые облегчают доказывать требуемые свойства определенных числовых алгоритмов.
Язык программирования Java требует, чтобы арифметика с плавающей точкой вела себя как будто каждый оператор с плавающей точкой, округленный ее результат с плавающей точкой к точности результата. Неточные результаты должны быть округлены к представимому значению, самому близкому к бесконечно точному результату; если два самых близких представимых значения одинаково рядом, тот, имеющий нуль, поскольку его младший значащий бит выбирается. Это - значение по умолчанию стандарта IEEE 754 округление режима, известного как вокруг самому близкому режиму.
Когда преобразование значения с плавающей точкой к целому числу, вокруг к нулевому режиму используется (§2.6.3). Вокруг к нулевым действиям режима, как если бы число было усеченным, отбрасывая биты мантиссы. Вокруг к нулевому режиму выбирает как его результат значение формата, самое близкое к и не больше в величине чем бесконечно точный результат.
Операторы с плавающей точкой языка программирования Java не производят исключений (§2.16). Работа, которая переполнения производят бесконечность со знаком; работа, которая потери значимости производят денормализованное значение или нуль со знаком; и работа, у которой нет никакого математически определенного результата, производит НЭН. Все числовые операции (за исключением числового сравнения) с НЭН как операнд производят НЭН в результате.
Любое значение любого типа с плавающей точкой может быть брошено (§2.6.9) к или от любого числового типа. Нет никаких бросков между типами с плавающей точкой и типом boolean
.
boolean
Значения boolean
выражения могут использоваться в операторах управления и как первый операнд условного оператора ?:
. Интегральное значение x
может быть преобразован в значение типа boolean
, после соглашения языка C, которое любое ненулевое значение true
, по выражению x!=0
. Ссылка на объект obj
может быть преобразован в значение типа boolean
, после соглашения языка C, что любая ссылка кроме null
true
, по выражению obj!=null
. Между типом нет никаких бросков boolean
и любой другой тип.
Экземпляр класса явно создается выражением создания экземпляра класса, или вызывая newInstance
метод класса Class
. Массив явно создается выражением создания массива. Объект создается в "куче" и собирается "мусор" после того, как нет больше ссылок на это. Объекты не могут быть исправлены или освобождены явными директивами языка.
Может быть много ссылок на тот же самый объект. У большинства объектов есть состояние, сохраненное в полях объектов, которые являются экземплярами классов или в переменных, которые являются компонентами объекта массива. Если две переменные содержат ссылки на тот же самый объект, состояние объекта может быть изменено, используя ссылку одной переменной на объект, и затем измененное состояние может наблюдаться через ссылку другой переменной.
У каждого объекта есть связанная блокировка (§2.19, §8.13), который используется synchronized
методы и synchronized
оператор, чтобы обеспечить управление параллельным доступом, чтобы утвердить многократными потоками (§2.19, §8.12).
Ссылочные типы формируют иерархию. Каждый тип класса является подклассом другого типа класса, за исключением класса Object
(§2.4.7), который является суперклассом (§2.8.3) всего другого класса и типов массива. Все объекты, включая массивы, поддерживают методы класса Object
. Строковые литералы (§2.3) являются ссылками на экземпляры класса String
(§2.4.8).
Object
Object
суперкласс (§2.8.3) всех других классов. Переменная типа Object
может содержать ссылку на любой объект, является ли это экземпляром класса или массива. Весь класс и типы массива наследовали методы класса Object
. String
String
представьте последовательности символов Unicode (§2.1). A String
у объекта есть постоянное, неизменное значение. Строковые литералы (§2.3) являются ссылками на экземпляры класса String
. instanceof
, и условный оператор ?:
. Совместимость значения переменной с ее типом гарантируется проектом языка, потому что значения по умолчанию (§2.5.1) являются совместимыми, и все присвоения на переменную проверяются, во время компиляции, для совместимости присвоения. Есть семь видов переменных:
static
(§2.9.1) в пределах объявления класса, или с или без ключевого слова static
в интерфейсном объявлении. Переменные класса создаются, когда класс или интерфейс загружаются (§2.17.2) и инициализируются на создании к значениям по умолчанию (§2.5.1). Переменная класса эффективно прекращает существование, когда ее класс или интерфейс разгружаются (§2.17.8).static
(§2.9.1). Если у класса T есть поле a, которое является переменной экземпляра, то новая переменная экземпляра создаваемого и инициализированного к значению по умолчанию (§2.5.1) как часть каждого недавно создаваемого объекта класса T или любого класса, который является подклассом T. Переменная экземпляра эффективно прекращает существование, когда, объектом которого это - поле, больше не ссылается, после любого необходимого завершения объекта был завершен (§2.17.7).catch
пункт a try
оператор (§2.16.2). Новая переменная инициализируется с фактическим объектом, связанным с исключением (§2.16.3). Параметр обработчика исключений эффективно прекращает существование когда выполнение блока, связанного с catch
пункт (§2.16.2) полон.for
оператор, новая переменная создается для каждой локальной переменной, объявленной в операторе объявления локальной переменной, сразу содержавшем в пределах того блока или for
оператор. Локальная переменная не инициализируется, однако, до оператора объявления локальной переменной, который объявляет, что это выполняется. Локальная переменная эффективно прекращает существование когда выполнение блока или for
оператор полон.
byte
, значение по умолчанию является нулем, то есть, значением (byte)0
.
short
, значение по умолчанию является нулем, то есть, значением (short)0
.
int
, значение по умолчанию является нулем, то есть, 0
.
long
, значение по умолчанию является нулем, то есть, 0L
.
float
, значение по умолчанию является положительным нулем, то есть, 0.0f
.
double
, значение по умолчанию является положительным нулем, то есть, 0.0
.
char
, значение по умолчанию является нулевым символом, то есть, '\u0000'
.
boolean
, значение по умолчанию false
.
null
(§2.3).
newInstance
метод, чтобы произвести объект. Этот класс вызывают классом объекта. Объект, как говорят, является экземпляром своего класса и всех суперклассов его класса. Иногда класс объекта вызывают, его "тип времени выполнения," но "класс" является более точным термином. (Иногда у переменной или выражения, как говорят, есть "тип времени выполнения," но это - злоупотребление терминологией; это обращается к классу объекта, упомянутого значением переменной или выражения во время выполнения, предполагая, что значение не null
. Должным образом разговор, тип является понятием времени компиляции. У переменной или выражения есть тип; объект или массив не имеют никакого типа, но принадлежат классу.)
Тип переменной всегда объявляется, и тип выражения может быть выведен во время компиляции. Тип ограничивает возможные значения, которые может содержать переменная, или выражение может произвести во время выполнения. Если значение времени выполнения является ссылкой, которая не является null
, это обращается к объекту, или выстройте, у которого есть класс (не тип), и тот класс обязательно будет совместимым с типом времени компиляции.
Даже при том, что у переменной или выражения может быть тип времени компиляции, который является интерфейсным типом, нет никаких экземпляров интерфейсов (§2.13). Переменная или выражение, тип которого является интерфейсным типом, могут сослаться на любой объект чьи реализации класса тот интерфейс.
У каждого массива также есть класс. У классов для массивов есть странные имена, которые не являются допустимыми идентификаторами; например, класс для массива int
у компонентов есть имя "[I"
.
Числовые продвижения являются преобразованиями, которые изменяют операнд числовой работы к более широкому типу, или оба операнда числовой работы к общему типу, так, чтобы работа могла быть выполнена.
В языке программирования Java есть шесть широких видов преобразований:
String
(§2.4.8).
+
и +=
операторы, когда одним из параметров является a String
; это не будет покрыто далее. byte
к short
, int
, long
, float
, или double
short
к int
, long
, float
, или double
char
к int
, long
, float
, или double
int
к long
, float
, или double
long
к float
или double
float
к double
float
к double
в strictfp
выражения (§2.18) также сохраняют числовое значение точно; однако, такие преобразования, которые не являются strictfp
может потерять информацию о полной величине преобразованного значения.
Преобразование int
или a long
значение к float
, или a long
значение к double
, может потерять точность, то есть, результат может потерять некоторые из младших значащих битов значения; получающееся значение с плавающей точкой является правильно округленной версией целочисленного значения, используя IEEE 754 вокруг для самого близкого режима (§2.4.4).
Согласно этому правилу, расширяющееся преобразование целого числа со знаком оценивает целочисленному типу, просто подписываются - расширяет two's-дополнительное представление целочисленного значения, чтобы заполнить более широкий формат. Расширяющееся преобразование значения типа char
к нулю целочисленного типа - расширяет представление символьного значения, чтобы заполнить более широкий формат.
Несмотря на то, что потеря точности может произойти, расширяя преобразования среди типов примитивов никогда не приводит к исключению на этапе выполнения (§2.16).
byte
к char
short
к byte
или char
char
к byte
или short
int
к byte
, short
, или char
long
к byte
, short
, char
, или int
float
к byte
, short
, char
, int
, или long
double
к byte
, short
, char
, int
, long
, или float
int
значение 32763
вводить byte
производит значение -5
). Сужение преобразований может также потерять точность.Сужающееся преобразование целого числа со знаком к целочисленному типу просто отбрасывает все кроме n битов самых низкоуровневых, где n является числом битов, используемых, чтобы представить тип. Это может заставить получающееся значение иметь различный знак от входного значения.
Сужающееся преобразование символа к целочисленному типу аналогично просто отбрасывает все кроме n самых низких битов, где n является числом битов, используемых, чтобы представить тип. Это может заставить получающееся значение быть отрицательным числом, даже при том, что символы представляют 16-разрядные значения целого без знака.
В сужающемся преобразовании числа с плавающей точкой к целочисленному типу, если числом с плавающей точкой является НЭН, результат преобразования 0
из соответствующего типа. Если число с плавающей точкой является слишком большим, чтобы быть представленным целочисленным типом или является положительной бесконечностью, результатом является самое большое представимое значение целочисленного типа. Если число с плавающей точкой является слишком маленьким, чтобы быть представленным или является отрицательной бесконечностью, результатом является самое маленькое представимое значение целочисленного типа. Иначе, результатом является число с плавающей точкой, округленное к нулю к целочисленному значению, используя IEEE 754 вокруг к нулевому режиму (§2.4.4)
Сужающееся преобразование из double
к float
ведет себя в соответствии с IEEE 754. Результат правильно округляется, используя IEEE 754 вокруг для самого близкого режима (§2.4.4). Значение, слишком маленькое, чтобы быть представленным как a float
преобразовывается в положительный или отрицательный нуль; значение, слишком большое, чтобы быть представленным как a float
преобразовывается в положительную или отрицательную бесконечность. A double
НЭН всегда преобразовывается в a
float
НЭН.
Несмотря на то, что переполнение, потеря значимости, или потеря точности могут произойти, сужая преобразования среди типов примитивов никогда не приводит к исключению на этапе выполнения.
Object
к любому другому типу класса.)
final
и не реализует K. (Важный особый случай - то, что есть сужающееся преобразование из типа класса Object
к любому интерфейсному типу.)
Object
к любому типу массива.
Object
к любому интерфейсному типу.
final
.
final
, при условии, что T реализует J.
[]
любому массиву вводят TC[]
, при условии, что SC и TC являются ссылочными типами и есть разрешенное преобразование сужения от SC до TC. ClassCastException
. Для каждой работы в выражении, которое не строго FP (§2.18), преобразование набора значений позволяет реализации языка программирования Java выбирать между двумя опциями:
Ли в строгом FP коде или коде, который не строг FP, преобразование набора значений всегда листы, неизменные любое значение, тип которого не является ни плаванием, ни двойной.
int
.
byte
, short
, или char
.
Если тип переменной float
или double
, тогда преобразование набора значений (§2.6.6) применяется после преобразования типов:
float
и элемент набора значений "расширенная экспонента плавающая", тогда реализация должна отобразить значение на самый близкий элемент набора значений плавающего. Это преобразование может привести к переполнению или потере значимости.
double
и элемент набора значений "двойная расширенная экспонента", тогда реализация должна отобразить значение на самый близкий элемент двойного набора значений. Это преобразование может привести к переполнению или потере значимости. boolean
может быть присвоен только переменной типа boolean
. Значение нулевого типа может быть присвоено переменной любого ссылочного типа.Присвоение значения ссылочного типа времени компиляции S (источник) к переменной ссылочного типа времени компиляции T (цель) разрешается:
Object
.
[]
, то есть, массив компонентов SC типа:
Object
.
Cloneable
или java.io.Serializable
.
[]
, то есть, массив компонентов TC типа, тогда также
Если тип выражения параметра является или плаванием или двойной, то преобразование набора значений (§2.6.6) применяется после преобразования типов:
float
элемент набора значений "расширенная экспонента плавающая", тогда реализация должна отобразить значение на самый близкий элемент набора значений плавающего. Это преобразование может привести к переполнению или потере значимости.
double
элемент набора значений "двойная расширенная экспонента", тогда реализация должна отобразить значение на самый близкий элемент двойного набора значений. Это преобразование может привести к переполнению или потере значимости. Преобразование набора значений (§2.6.6) применяется после преобразования типов.
Кастинг может преобразовать значение любого числового типа к любому другому числовому типу. Значение типа boolean
не может быть брошен к другому типу. Значение ссылочного типа не может быть брошено к значению типа примитива.
Некоторые броски могут быть доказаны неправильными во время компиляции и результат в ошибке времени компиляции. Иначе, или бросок может быть доказан корректным во время компиляции, или проверка достоверности времени выполнения требуется. (См. Спецификацию языка JavaTM для деталей.), Если значение во время выполнения является нулевой ссылкой, то бросок позволяется. Если проверка в сбоях времени выполнения, a ClassCastException
бросается.
Числовые продвижения используются, чтобы преобразовать операнды числового оператора к общему типу, где работа может быть выполнена. Два вида числового продвижения являются унарным числовым продвижением и двоичным числовым продвижением. Аналогичные преобразования в C вызывают "обычными унарными преобразованиями" и "обычными двоичными преобразованиями." Числовое продвижение не является общей функцией языка программирования Java, а скорее свойством определенных встроенных операторов.
Оператор, который применяет унарное числовое продвижение единственному операнду числового типа, преобразовывает операнд типа byte
, short
, или char
к int
расширяющимся примитивным преобразованием, и иначе оставляет операнд в покое. Преобразование набора значений (§2.6.6) тогда применяется. Операнды операторов сдвига продвигаются, независимо используя унарные числовые продвижения.
Когда оператор применяет двоичное числовое продвижение паре числовых операндов, следующие правила применяются, в порядке, используя расширение примитивного преобразования, чтобы преобразовать операнды по мере необходимости:
double
, другой преобразовывается в double
.
float
, другой преобразовывается в float
.
long
, другой преобразовывается в long
.
int
. Не все идентификаторы являются частью имени. Идентификаторы также используются в объявлениях, где идентификатор определяет имя, которым объект будет известен в выражениях доступа к полю и выражениях вызова метода, и в метках оператора и break
и continue
операторы, которые обращаются к меткам оператора.
Имя компонента имени пакета или имя класса могли бы содержать символ, который не может по закону появиться в обычном каталоге файловой системы узла или имени файла: например, символ Unicode на системе, которая позволяет только символы ASCII в именах файлов.
Реализация виртуальной машины Java должна поддерживать по крайней мере один неназванный пакет; это может поддерживать больше чем один, но не обязано делать так. То, какие единицы компиляции находятся в каждом неназванном пакете, определяется хост-системой. Неназванные пакеты обеспечиваются преимущественно для удобства, разрабатывая маленькие или временные приложения или только начиная разработку.
import
объявление позволяет тип, который, как объявляют в другом пакете, был известен простым именем, а не полностью определенным именем (§2.7.5) типа. Объявление импорта влияет только на описания типа единственной единицы компиляции. Единица компиляции автоматически импортирует каждый из public
имена типов объявляются в предопределенном пакете java.lang
.
java
всегда имеет подпакеты lang
, util
, io
, и net
. Ни у каких двух отличных элементов того же самого пакета не может быть того же самого простого имени (§2.7.1), но у элементов различных пакетов может быть то же самое простое имя. У типа класса может быть два или больше метода с тем же самым простым именем, если у них есть различные числа параметров, или различный параметр вводит по крайней мере одну позицию параметра. Такое имя элемента метода, как говорят, перегружается. Тип класса может содержать объявление для метода с тем же самым именем и той же самой подписью как метод, который был бы иначе наследован от суперкласса или суперинтерфейса. В этом случае метод суперкласса или суперинтерфейса не наследован. Если метод, не наследованный, abstract
, новое объявление, как говорят, реализует метод; если это не abstract
, новое объявление, как говорят, переопределяет это.
Object
(§2.4.7), и поле length
, который является константой (final
) поле каждого массива. Язык программирования Java обеспечивает механизмы для того, чтобы они ограничили квалифицированный доступ, предотвратили пользователей пакета или класса от в зависимости от ненужных деталей реализации того пакета или класса. Управление доступом также применяется к конструкторам.
Доступен ли пакет, определяется хост-системой.
Класс или интерфейс могут быть объявлены public
, когда к этому может получить доступ, используя полностью определенное имя, любой класс или взаимодействовать через интерфейс, который может получить доступ к пакету, в котором это объявляется. Класс или интерфейс, который не объявляется public
от можно получить доступ, и только от, где угодно в пакете, в котором это объявляется.
Каждое поле или метод интерфейса должны быть public
. Каждый элемент a public
интерфейс неявно public
, действительно ли ключевое слово public
появляется в его объявлении. Из этого следует, что элемент интерфейса доступен, если и только если сам интерфейс доступен.
Поле, метод, или конструктор класса могут быть объявлены, используя самое большее один из public
, private
, или protected
ключевые слова. A public
к элементу могут получить доступ любой класс или интерфейс. A private
к элементу можно получить доступ только изнутри класса, который содержит его объявление. Элемент, который не объявляется public
, protected
, или private
как говорят, имеет доступ по умолчанию и может быть получен доступ от, и только от, где угодно в пакете, в котором он объявляется.
A protected
к элементу объекта может получить доступ только код, ответственный за реализацию того объекта. Быть точным, a protected
к элементу можно получить доступ отовсюду в пакете, в котором он объявляется и, кроме того, к нему можно получить доступ изнутри любого объявления подкласса типа класса, который содержит его объявление, при условии, что определенным ограничениям повинуются.
boolean
, char
, byte
, short
, int
, long
, float
, или double
.
.
"сопровождаемый простым (элемент) имя подпакета.
.
"сопровождаемый простым именем класса или интерфейса.
[]
". Тело класса объявляет элементы (поля и методы), статические инициализаторы, и конструкторы.
.
Идентификатор. Если класс находится в неназванном пакете, то у класса есть полностью определенный Идентификатор имени. Два класса являются тем же самым классом (и поэтому тот же самый тип), если они загружаются тем же самым загрузчиком класса (§2.17.2), и у них есть то же самое полностью определенное имя (§2.7.5).
public
, как обсуждено в §2.7.4. abstract
класс является классом, который является неполным, или рассмотренный неполным. Только abstract
классы могут иметь abstract
методы (§2.10.3), то есть, методы, которые объявляются, но еще не реализуются.
Класс может быть объявлен final
если его определение полно, и никакие подклассы не требуются или требуются. Поскольку a final
у класса никогда нет подклассов, методов a final
класс не может быть переопределен в подклассе. Класс не может быть обоими final
и abstract
, потому что реализация такого класса никогда не могла завершаться.
Класс может быть объявлен strictfp
указать, что все выражения в методах класса строги FP (§2.18), объявляются ли сами методы строгие FP.
Класс объявляется public
сделать его тип доступным для пакетов кроме того, в котором это объявляется. A public
класс доступен от других пакетов, используя или его полностью определенное имя или более короткое имя, создаваемое import
объявление (§2.7.2), всякий раз, когда узел разрешает доступ к своему пакету. Если классу недостает public
модификатор, доступ к объявлению класса ограничивается пакетом, в котором это объявляется.
extends
пункт в объявлении класса определяет прямой суперкласс текущего класса, класса, из реализации которого получается реализация текущего класса. Класс, как говорят, является прямым подклассом класса это extends
. Только класс Object
(у §2.4.7) нет никакого прямого суперкласса. Если extends
пункт опускается от объявления класса, тогда суперкласс нового класса Object
. Отношение подкласса является переходным закрытием прямого отношения подкласса. Класс A является подклассом класса C, если A является прямым подклассом C, или если есть прямой подкласс B C, и класс A является подклассом Б. Класс А, как, говорят, суперкласс класса C всякий раз, когда C является подклассом A.
Object
, у которого нет никакого прямого суперкласса.
private
не наследованы подклассами того класса. Элементы класса, которые не объявляются private
, protected
, или public
не наследованы подклассами, объявленными в пакете кроме того, в котором объявляется класс. Конструкторы (§2.12) и статические инициализаторы (§2.11) не являются элементами и поэтому не наследованы.static
) переменные существуют однажды на класс. Переменные экземпляра существуют однажды на экземпляр класса. Поля могут включать инициализаторы и могут быть изменены, используя различные ключевые слова модификатора. Если класс объявляет поле с определенным именем, то объявление того поля, как говорят, скрывает любого и все доступные объявления полей с тем же самым именем в суперклассах и суперинтерфейсах класса. Класс наследовал от его прямого суперкласса и прямых суперинтерфейсов все поля суперкласса и суперинтерфейсов, которые доступны, чтобы кодировать в классе и не скрываются объявлением в классе. К скрытому полю можно получить доступ при использовании полностью определенного имени (если это static
) или при использовании выражения доступа к полю, которое содержит бросок к супертипу класса или ключевому слову super
.
Значение, сохраненное в поле плавания типа, всегда является элементом набора значений плавающего (§2.4.3); точно так же значение, сохраненное в поле двойного типа, всегда является элементом двойного набора значений. Не разрешается для поля плавания типа содержать элемент набора значений "расширенная экспонента плавающая", которая не является также элементом набора значений плавающего, ни для поля типа, двойного, чтобы содержать элемент набора значений "двойная расширенная экспонента", которая не является также элементом двойного набора значений.
public
, protected
, или private
, как обсуждено в §2.7.4. Если поле объявляется static
, там существует точно одно воплощение поля, независимо от того сколько экземпляров (возможно нуль) класса может в конечном счете быть создано. A static
поле, иногда называемое переменной класса, воплощается, когда класс инициализируется (§2.17.4).
Поле, которое не объявляется static
вызывается переменной экземпляра. Всякий раз, когда новый экземпляр класса создается, новая переменная, связанная с тем экземпляром, создается для каждой переменной экземпляра, объявленной в том классе или в любом из его суперклассов.
Поле может быть объявлено final
, когда его оператор объявления должен включать переменный инициализатор (§2.9.2). И класс и переменные экземпляра (static
и не -static
поля), может быть объявлен final
. Однажды a final
поле было инициализировано, оно всегда содержит то же самое значение. Если a final
поле содержит ссылку на объект, тогда состояние объекта может быть изменено операциями на объекте, но поле будет всегда обращаться к тому же самому объекту.
Переменные могут быть отмечены transient
указать, что они не часть постоянного состояния объекта. transient
атрибут может использоваться реализацией, чтобы поддерживать специальные системные службы. Спецификация языка JavaTM еще не определяет детали таких служб.
Язык программирования Java позволяет потокам что совместно используемые переменные доступа сохранять частные рабочие копии переменных; это позволяет более эффективную реализацию многократных потоков (§2.19). Эти рабочие копии должны быть согласованы с основными копиями в совместно используемой основной памяти только в предписанных точках синхронизации, а именно, когда объекты блокируются или разблокировались (§2.19). Как правило, чтобы удостовериться, что совместно используемые переменные последовательно и достоверно обновляются, поток должен гарантировать, что у него есть эксклюзивный доступ к таким переменным, получая блокировку, которая традиционно осуществляет взаимное исключение для тех совместно используемых переменных.
Альтернативно, поле может быть объявлено volatile
, когда поток должен согласовать свою рабочую копию поля с основной копией каждый раз, когда это получает доступ к переменной. Кроме того операции на основных копиях одной или более энергозависимых переменных от имени потока выполняются основной памятью в точно порядке что поток, который требуют. A final
поле не может также быть объявлено volatile
.
static
поле), тогда переменный инициализатор оценивается и присвоение, выполняемое точно однажды, когда класс инициализируется (§2.17.4).
static
), тогда переменный инициализатор оценивается и присвоение, выполняемое каждый раз, когда экземпляр класса создается. super
ключевое слово. Параметр метода плавания типа всегда содержит элемент набора значений плавающего (§2.4.3); точно так же параметр метода типа, двойного всегда, содержит элемент двойного набора значений. Не разрешается для параметра метода плавания типа содержать элемент набора значений "расширенная экспонента плавающая", которая не является также элементом набора значений плавающего, ни для параметра метода типа, двойного, чтобы содержать элемент набора значений "двойная расширенная экспонента", которая не является также элементом двойного набора значений.
Где фактическое выражение параметра, соответствующее переменной параметра, не строго FP (§2.18), оценке того фактического выражения параметра разрешают использовать значения, оттянутые из соответствующих наборов значений расширенной экспоненты. До того, чтобы быть сохраненным в переменной параметра результат такого выражения отображается на самое близкое значение в соответствующем стандартном наборе значений преобразованием вызова метода (§2.6.8).
public
, protected
, и private
обсуждаются в Разделе 2.7.4. abstract
объявление метода представляет метод, поскольку элемент, обеспечивая его подпись (§2.10.2), возвращает тип, и throws
пункт (если кто-либо), но не обеспечивает реализацию. Объявление abstract
метод м. должен появиться в пределах abstract
класс (вызывают это A). Каждый подкласс, который не является самостоятельно abstract
должен обеспечить реализацию для м. Метод объявляется abstract
как могут также объявлять, не private
, static
, final
, native
, strictfp
, или synchronized
.
Метод, который объявляется static
вызывается методом класса. Метод класса всегда вызывается независимо от определенного объекта. Метод класса может обратиться к другим полям и методам класса простым именем, только если они - методы класса и класс (static
) переменные.
Метод, который не объявляется static
метод экземпляра. Метод экземпляра всегда вызывается относительно объекта, который становится текущим объектом к который ключевые слова this
и super
отнеситесь во время выполнения тела метода.
Метод может быть объявлен final
препятствовать тому, чтобы подклассы переопределили или скрыли это. A private
метод и все методы объявляются в a final
класс (§2.8.2) неявно final
, потому что невозможно переопределить их. Если метод final
или неявно final
, компилятор или генератор кода времени выполнения могут безопасно "встроить" тело a final
метод, заменяя вызов метода с кодом в его теле.
A synchronized
метод получит блокировку монитора (§2.19) прежде, чем он выполнится. Для класса (static
) метод, блокировка, связанная с объектом класса для класса метода, используется. Для метода экземпляра, блокировка, связанная с this
(объект, для которого вызывается метод) используется. Та же самая блокировка на объект используется synchronized
оператор.
Метод может быть объявлен strictfp
указать, что все выражения в методе строги FP (§2.18).
Метод может быть объявлен native
указать, что это реализуется в зависимом от платформы коде, обычно записанном в другом языке программирования, таком как C, C++, или ассемблер. Метод, как могут объявлять, не является обоими native
и strictfp
.
Статические инициализаторы и инициализаторы переменной класса выполняются в текстовом порядке. Они, возможно, не обращаются к переменным класса, объявленным в классе, объявления которого появляются дословно после использования, даже при том, что эти переменные класса находятся в контексте. Это ограничение разрабатывается, чтобы поймать, во время компиляции, наиболее круговой или иначе уродливые инициализации.
+
, и явными вызовами конструктора от других конструкторов; они никогда не вызываются выражениями вызова метода. Объявления конструктора не являются элементами. Они никогда не наследованы и поэтому не подвергаются сокрытию или переопределению.
Если тело конструктора не начинается с явного вызова конструктора, и объявляемый конструктор не является частью исконного класса Object
, тогда тело конструктора, как неявно предполагает компилятор, начинается с вызова конструктора суперкласса"super();
", вызов конструктора прямого суперкласса, который не берет параметров.
Если класс не объявляет конструкторов тогда конструктор по умолчанию, который не берет параметров, автоматически обеспечивается. Если объявляемый класс Object
, тогда у конструктора по умолчанию есть пустое тело. Иначе, конструктор по умолчанию не берет параметров и просто вызывает конструктора суперкласса без параметров. Если класс объявляется public
, тогда конструктору по умолчанию неявно дают модификатор доступа public
. Иначе, конструктору по умолчанию подразумевал доступ по умолчанию никакой модификатор доступа (§2.7.4).
Класс может быть разработан, чтобы предотвратить код вне объявления класса от создания экземпляров класса, объявляя по крайней мере одного конструктора, чтобы предотвратить создание неявного конструктора, и объявляя, что все конструкторы private
.
public
, protected
, и private
(§2.7.4). Конструктор не может быть abstract
, static
, final
, native
, или synchronized
. Конструктор, как могут объявлять, не strictfp
. Этим различием в определениях для модификаторов метода (§2.10.3) и модификаторов конструктора является намеренное проектное решение языка; это эффективно гарантирует, что конструктор строг FP (§2.18), если и только если его класс строг FP, так сказать.
abstract
методы. У этого типа нет никакой реализации, но иначе несвязанные классы могут реализовать его, обеспечивая реализации для abstract
методы. Программы могут использовать интерфейсы, чтобы сделать это ненужным для связанных классов, чтобы совместно использовать общее abstract
суперкласс или добавить методы к Object
. Интерфейс, как могут объявлять, является прямым расширением одного или более других интерфейсов, означая, что он неявно определяет весь abstract
методы и константы интерфейсов, которые это расширяет, за исключением любых констант, которые это может скрыть, и возможно добавляет недавно объявленные собственные элементы.
Класс, как могут объявлять, непосредственно реализует один или более интерфейсов, означая, что любой экземпляр класса реализует весь abstract
методы определяются тем интерфейсом. Класс обязательно реализует все интерфейсы, которые делают его прямые суперклассы и прямые суперинтерфейсы. Это (многократное) интерфейсное наследование позволяет объектам поддерживать (многократные) общие поведения, не совместно используя реализации.
Переменная, чья объявленный типом интерфейсный тип, может иметь как его значение ссылка на объект, который является экземпляром любого класса, который, как объявляют, реализует указанный интерфейс. Не достаточно, что класс, оказывается, реализует весь abstract
методы интерфейса; класс или один из его суперклассов, как должны фактически объявлять, реализуют интерфейс, или иначе класс, как полагают, не реализует интерфейс.
public
, strictfp
, и abstract
. Модификатор доступа public
обсуждается в (§2.7.4). Каждый интерфейс неявно abstract
. Все элементы интерфейсов неявно public
. Интерфейс не может быть final
, потому что реализация такого класса никогда не могла завершаться.
extends
пункт обеспечивается, тогда объявляемый интерфейс расширяет каждый из других именованных интерфейсов и поэтому наследовал методы и константы каждого из других именованных интерфейсов. Любой класс это implements
объявленный интерфейс, как также полагают, реализует все интерфейсы, которые расширяет этот интерфейс и которые доступны для класса. implements
пункт в объявлении класса перечисляет имена интерфейсов, которые являются прямыми суперинтерфейсами объявляемого класса. Все интерфейсы в текущем пакете доступны. Интерфейсы в других пакетах доступны, если хост-система разрешает доступ к пакету, и интерфейс объявляется public
.
Интерфейсный K типа является суперинтерфейсом типа класса C, если K является прямым суперинтерфейсом C; или если у C есть прямой суперинтерфейс J, у которого есть K как суперинтерфейс; или если K является суперинтерфейсом прямого суперкласса C. Класс, как говорят, реализует все свои суперинтерфейсы.
Нет никакого аналога класса Object
для интерфейсов; то есть, в то время как каждый класс является расширением класса Object
, нет никакого единственного интерфейса, которого все интерфейсы являются расширениями.
static
и final
. У интерфейсов нет переменных экземпляра. Каждое полевое объявление в интерфейсе самостоятельно неявно public
. Объявление константы в интерфейсе не должно включать ни один из модификаторов transient
или volatile
. У каждого поля в теле интерфейса должно быть выражение инициализации, которое не должно быть константным выражением. Переменный инициализатор оценивается и присвоение, выполняемое точно однажды, когда интерфейс инициализируется (§2.17.4).
abstract
и неявно public
. Метод, объявленный в теле интерфейса, не должен быть объявлен static
, потому что static
методы не могут быть abstract
.
Метод, объявленный в теле интерфейса, не должен быть объявлен native
, strictfp
, или synchronized
, потому что те ключевые слова описывают свойства реализации, а не интерфейсные свойства; однако, метод, объявленный в интерфейсе, может быть реализован методом, который объявляется native
, strictfp
, или synchronized
в классе, который реализует интерфейс. Метод, объявленный в теле интерфейса, не должен быть объявлен final
; однако, можно быть реализован методом, который объявляется final
в классе, который реализует интерфейс.
Интерфейс наследовал от его прямых суперинтерфейсов все методы суперинтерфейсов, которые не переопределяются методом, объявленным в интерфейсе.
Если два метода интерфейса (объявляются ли оба в том же самом интерфейсе, или оба наследованы интерфейсом, или каждый объявляется, и каждый наследован), имеют то же самое имя, но различные подписи, то имя метода, как говорят, перегружается.
Полная спецификация вложенных классов и интерфейсов будет опубликована во втором выпуске Спецификации языка JavaTM. До тех пор заинтересованные люди должны обратиться к Внутренней Спецификации Классов, которая может быть найдена в http://java.sun.com/products/jdk/1.1/docs/guide/innerclasses/spec/innerclasses.doc.html
.
Object
(§2.4.7). Все методы на массивах унаследованы от класса Object
кроме clone
метод, который выстраивает переопределение. Все массивы реализуют интерфейсы Cloneable
и java.io.Serializable
. Объект массива содержит много переменных. То число может быть нулем, когда массив, как говорят, пуст. У переменных, содержавшихся в массиве, нет никаких имен; вместо этого на них ссылаются выражения доступа массива, которые используют неотрицательные целочисленные индексные значения. Эти переменные вызывают компонентами массива. Если у массива есть n компоненты, мы говорим, что n является длиной массива.
Массив нулевых компонентов не является тем же самым как нулевой ссылкой (§2.4).
Компонент массива плавания типа всегда является элементом набора значений плавающего (§2.4.3); точно так же компонент двойного типа всегда является элементом двойного набора значений. Компонент плавания типа, возможно, не элемент набора значений "расширенная экспонента плавающая", если это не также элемент набора значений плавающего. Компонент двойного типа, возможно, не элемент набора значений "двойная расширенная экспонента", если это не также элемент двойного набора значений.
[]
. Компонентный тип массива может самостоятельно быть типом массива. Компоненты такого массива могут содержать ссылки на подмассивы. Если, запускаясь с какого-либо типа массива, каждый рассматривает его компонентный тип, и затем (если это - также тип массива), компонентный тип того типа, и так далее, в конечном счете нужно достигнуть компонентного типа, который не является типом массива; это вызывают типом элемента исходного массива, и компоненты на этом уровне структуры данных вызывают элементами исходного массива.
Есть три ситуации, в которых элемент массива может быть массивом: если тип элемента имеет тип Object
(§2.4.7), Cloneable
, или java.io.Serializable
, тогда некоторые или все элементы могут быть массивами, потому что каждый объект массива может быть присвоен переменной одного из тех типов.
В языке программирования Java, в отличие от этого в C, массиве char
не a String
(§2.4.7), и ни один a String
ни массив char
завершается '\u0000'
( NUL
Символьный). A String
объект является неизменным (его значение никогда не изменяется), в то время как массив char
имеет изменчивые элементы.
Тип элемента массива может быть любым типом, или примитивный или ссылочный. В частности массивы с интерфейсным типом как компонентный тип поддерживаются; элементы такого массива могут иметь как их значение нулевая ссылка или экземпляры любого типа класса, который реализует интерфейс. Массивы с abstract
тип класса как компонентный тип поддерживается; элементы такого массива могут иметь как их значение нулевая ссылка или экземпляры любого подкласса этого abstract
класс, который не является самостоятельно abstract
.
Поскольку длина массива не является частью своего типа, единственная переменная типа массива может содержать ссылки на массивы различных длин. Как только объект массива создается, его длина никогда не изменяется. Чтобы заставить переменную типа массив обратиться к массиву различной длины, ссылка на различный массив должна быть присвоена переменной.
Если у переменной типа массив v есть тип A[]
, где A является ссылочным типом, тогда v может содержать ссылку на любой тип B массива[]
, если B может быть присвоен (§2.6.7).
int
значения; short
, byte
, или char
значения могут также использоваться, поскольку они подвергаются унарному числовому продвижению (§2.6.10) и становятся int
значения. Все массивы с 0 источниками. Массив с длиной n может быть индексирован целыми числами 0 через n - 1. Во время выполнения проверяются все доступы массива; попытка использовать индекс, который является меньше чем нуль или больше чем или равный длине массива, вызывает ArrayIndexOutOfBoundsException
быть брошенным.
Программы могут также выдать исключения явно, используя throw
операторы. Это обеспечивает альтернативу старомодному стилю условий ошибки из-за неправильного обращения, возвращая отличенные ошибочные значения, такие как целочисленное значение -1
, где отрицательная величина обычно не ожидалась бы.
Каждое исключение представляется экземпляром класса Throwable
или один из его подклассов; такой объект может использоваться, чтобы перенести информацию от точки, в которой исключение происходит с обработчиком, который ловит это. Обработчики устанавливаются catch
пункты try
операторы. Во время процесса выдачи исключения виртуальная машина Java резко завершает, один за другим, любые выражения, операторы, метод и вызовы конструктора, статические инициализаторы, и полевые выражения инициализации, которые начали, но не завершили выполнение в текущем потоке. Этот процесс продолжается, пока обработчик не находится, который указывает, что это обрабатывает выданное исключение, называя класс исключения или суперкласс класса исключения. Если никакой такой обработчик не находится, то метод uncaughtException
вызывается для ThreadGroup
это - родитель текущего потока.
В языке программирования Java механизм исключения интегрируется с моделью синхронизации (§2.19) так, чтобы блокировки были должным образом выпущены как synchronized
операторы и так, чтобы вызовы synchronized
методы завершаются резко.
Определенные исключения, покрытые этим разделом, - то, что подмножество предопределенных исключений, которые могут быть выданы непосредственно работой виртуальной машины Java. Дополнительные исключения могут быть выданы пользовательским кодом или библиотекой классов; эти исключения не покрываются здесь. См. Спецификацию языка JavaTM для информации обо всех предопределенных исключениях.
throw
оператор выполнялся.
stop
метод класса Thread
или ThreadGroup
был вызван, или
Throwable
и экземпляры его подклассов. Эти классы являются, все вместе, классами исключений.catch
пункт a try
оператор, который обрабатывает исключение. Оператор или выражение динамически включаются a catch
пункт, если это появляется в пределах try
блок try
оператор которого catch
пункт является частью, или если вызывающая сторона оператора или выражения динамически включается catch
пункт.
Вызывающая сторона оператора или выражения зависит от того, где это происходит:
newInstance
это выполнялось, чтобы заставить объект создаваться.
static
переменная, тогда вызывающая сторона является выражением, которое использовало класс или интерфейс, чтобы заставить это быть инициализированным. catch
дескрипторы пункта исключение определяется, сравнивая класс объекта, который был брошен в объявленный тип параметра catch
пункт. catch
пункт обрабатывает исключение, если тип его параметра является классом исключения или суперклассом класса исключения. Эквивалентно, a catch
пункт поймает любой объект исключения, который является instanceof
объявленный тип параметра.
Передача управления, которая происходит, когда исключение выдается причины резкое завершение выражений и операторов до a catch
с пунктом встречаются, который может обработать исключение; выполнение тогда продолжается, выполняя блок этого catch
пункт. Код, который вызвал исключение, никогда не возобновляется.
Если нет catch
пункт, обрабатывающий исключение, может быть найден, тогда текущий поток (поток, который встречался, исключение) завершается, но только в конце концов finally
пункты были выполнены и метод uncaughtException
был вызван для ThreadGroup
это - родитель текущего потока.
В ситуациях, где это является требуемым, чтобы гарантировать, что один блок кода всегда выполняется за другим, даже если тот другой блок кода завершается резко, a try
оператор с a finally
пункт может использоваться. Если a try
или catch
блок в a try-finally
или try-catch-finally
оператор завершается резко, тогда finally
пункт выполняется во время распространения исключения, даже если никакое соответствие catch
пункт в конечном счете находится. Если a finally
пункт выполняется из-за резкого завершения a try
блок и finally
сам пункт завершается резко, тогда причина резкого завершения try
блок отбрасывается, и новая причина резкого завершения распространяется оттуда.
Большинство исключений происходит синхронно в результате действия потоком, в котором они происходят и в точке в программе, которая определяется, чтобы возможно привести к такому исключению. Асинхронное исключение является, в отличие от этого, исключением, которое может потенциально произойти в любой точке в выполнении программы.
Асинхронные исключения редки. Они происходят только в результате:
stop
метод класса Thread
или ThreadGroup
.
stop
метод может быть вызван одним потоком, чтобы влиять на другой поток или все потоки в указанной группе потока. Это является асинхронным, потому что это может произойти в любой точке в выполнении другого потока или потоков. Внутреннюю ошибку считают асинхронной так, чтобы она могла быть обработана, используя тот же самый механизм, который обрабатывает stop
метод, как будет теперь описан. Язык программирования Java разрешает небольшому, но ограниченному количеству выполнения происходить прежде, чем асинхронное исключение будет выдано. Этой задержке разрешают позволить оптимизированному коду обнаруживать и выдавать эти исключения в точках, где это практично, чтобы обработать их, повинуясь семантике языка.
Простая реализация могла бы опросить относительно асинхронных исключений в точке каждой инструкции передачи управления. Так как у программы есть конечный размер, это обеспечивает привязанный полная задержка обнаружения асинхронного исключения. Так как никакое асинхронное исключение не произойдет между передачами управления, у генератора кода есть некоторая гибкость, чтобы переупорядочить вычисление между передачами управления для большей производительности.
Все исключения в языке программирования Java точны: когда передача управления имеет место, все эффекты выполняемых операторов и выражения, оцененные перед, точка, от которой выдается исключение, должно казаться, имела место. Никакие выражения, операторы, или части этого, которые происходят после точки, от которой выдается исключение, может казаться, не были оценены. Если оптимизированный код теоретически выполнил некоторые из выражений или операторов, которые следуют за точкой, в которой происходит исключение, такой код должен быть подготовлен скрыть это спекулятивное выполнение от видимого пользователем состояния программы.
Throwable
, прямой подкласс Object
. Классы Exception
и Error
прямые подклассы Throwable
. Класс RuntimeException
прямой подкласс Exception
. Программы могут использовать существующие ранее классы исключений в throw
операторы, или определяют дополнительные классы исключений как подклассы Throwable
или любого из его подклассов, как соответствующий. Чтобы использовать в своих интересах время компиляции, проверяя на обработчики исключений, это типично, чтобы определить самые новые классы исключений как проверенные классы исключений, определенно как подклассы Exception
это не подклассы RuntimeException
.
Exception
и RuntimeException
Exception
суперкласс всех стандартных исключений, с которых обычные программы могут хотеть восстановиться. Класс RuntimeException
подкласс класса Exception
. Подклассы RuntimeException
классы исключений непроверенные. Пакет java.lang
определяет следующие стандартные исключения на этапе выполнения непроверенные:
ArithmeticException
: Исключительная арифметическая ситуация возникла, такие как целочисленное деление или целочисленная работа остатка с делителем нуля.
ArrayStoreException
: Попытка была предпринята, чтобы сохранить в компонент массива значение, класс которого не является присвоением, совместимым с компонентным типом массива.
ClassCastException
: Попытка была предпринята, чтобы бросить ссылку на объект к несоответствующему типу.
IllegalMonitorStateException
: Поток попытался ожидать на или уведомить другие потоки, ожидающие относительно объекта, что он не заблокировал.
IndexOutOfBoundsException
: Или индекс некоторого вида (такой относительно массива, строки, или вектор) или поддиапазон, определенный или двумя индексными значениями или индексом и длиной, испытывал недостаток диапазона.
NegativeArraySizeException
: Попытка была предпринята, чтобы создать массив с отрицательной длиной.
NullPointerException
: Попытка была предпринята, чтобы использовать нулевую ссылку в случае, где ссылка на объект требовалась.
SecurityException
: Нарушение защиты было обнаружено. Error
и его стандартные подклассы являются исключениями, с которых обычные программы, как обычно ожидают, не восстановятся. Класс Error
отдельный подкласс Throwable
, отличный от Exception
в иерархии классов, чтобы позволить программам использовать идиому
} catch (Exception e) {
поймать все исключения, от которых восстановление может быть возможным, не фиксируя ошибки, от которых восстановление обычно не возможно. Пакет java.lang
определяет все ошибочные классы, описанные здесь. Виртуальная машина Java бросает объект, который является экземпляром подкласса LinkageError
когда загрузка (§2.17.2), соединяясь (§2.17.3), или инициализация (§2.17.4) ошибка происходит.
ClassFormatError
, ClassCircularityError
, NoClassDefFoundError
, и UnsupportedClassVersionError
описываются там.
NoSuchFieldError
, NoSuchMethodError
, InstantiationError
, и IllegalAccessError
описываются там.
VerifyError
описывается там.
ExceptionInInitializerError
если выполнение статического инициализатора или инициализатора для a static
поле (§2.11) приводит к исключению, которое не является Error
или подкласс Error
.A LinkageError
май также быть брошенным во время выполнения:
AbstractMethodError
бросается во время выполнения если abstract
метод вызывается.
UnsatisfiedLinkError
бросается во время выполнения, если виртуальная машина Java не может счесть соответствующее определение метода объявленным быть native
. VirtualMachineError
когда внутреннее ограничение ошибки или ресурса препятствует тому, чтобы это реализовало семантику языка программирования Java. Эта спецификация определяет следующие ошибки виртуальной машины:
InternalError
: Внутренняя ошибка произошла в реализации виртуальной машины Java из-за отказа в программном обеспечении, реализовывая виртуальную машину, отказ в базовом программном обеспечении хост-системы, или отказ в аппаратных средствах. Эта ошибка поставляется асинхронно, когда она обнаруживается и может произойти в любой точке в программе.
OutOfMemoryError
: Реализация виртуальной машины Java исчерпала или виртуальную память или физическую память, и автоматический менеджер по хранению был неспособен исправить достаточно памяти, чтобы удовлетворить объектный запрос создания.
StackOverflowError
: Реализация виртуальной машины Java исчерпала стековое пространство для потока, обычно потому что поток делает неограниченное число рекурсивных вызовов в результате отказа в программе выполнения.
UnknownError
: Исключение или ошибка произошли, но реализация виртуальной машины Java неспособна сообщить о фактическом исключении или ошибке. main
из некоторого указанного класса и передачи этого единственный параметр, который является массивом строк. Это заставляет указанный класс быть загруженным (§2.17.2), соединялся (§2.17.3) с другими типами, которые это использует, и инициализированный (§2.17.4). Метод main
должен быть объявлен public
, static
, и void
. Способ, которым начальный класс определяется к виртуальной машине Java, выходит за рамки этой спецификации, но это типично в средах узла, которые используют командные строки для полностью определенного имени класса, который будет определен как параметр командной строки и для последующих параметров командной строки, которые будут использоваться в качестве строк, которые будут обеспечены как параметр методу main
. Например, используя Java Sun 2 SDK для Соляриса, командной строки
java Terminator Hasta la vista Baby!
запустит виртуальную машину Java, вызывая метод main
из класса Terminator
(класс в неназванном пакете) и передача этого массив, содержащий четыре строки "Hasta"
, "la"
, "vista"
, и "Baby!"
. Мы теперь обрисовываем в общих чертах шаги, которые виртуальная машина может сделать, чтобы выполниться Terminator
, как пример загрузки, соединения, и процессов инициализации, которые описываются далее в более поздних разделах.
Начальная попытка выполнить метод main
из класса Terminator
обнаруживает что класс Terminator
не загружается - то есть, виртуальная машина в настоящий момент не содержит двоичное представление для этого класса. Виртуальная машина тогда использует a ClassLoader
(§2.17.2), чтобы попытаться найти такое двоичное представление. Если этот процесс перестал работать, ошибка бросается. Этот процесс загрузки описывается далее в (§2.17.2).
После Terminator
загружается, это должно быть инициализировано прежде main
может быть вызван, и тип (класс или интерфейс) должен всегда соединяться прежде, чем это будет инициализировано. Соединение (§2.17.3) включает проверку, подготовку, и (дополнительно) разрешение.
Проверка (§2.17.3) проверяет что загруженное представление Terminator
хорошо формируется, с надлежащей таблицей символов. Проверка также проверяет, что код, который реализует Terminator
повинуется семантическим требованиям виртуальной машины Java. Если проблема обнаруживается во время проверки, ошибка бросается.
Подготовка (§2.17.3) включает выделение статического хранения и любых структур данных, которые используются внутренне виртуальной машиной, такой как таблицы метода.
Разрешение (§2.17.3) является процессом проверки символьных ссылок от класса Terminator
к другим классам и интерфейсам, загружая другие классы и интерфейсы, которые упоминаются и проверяя, что ссылки корректны.
Шаг разрешения является дополнительным во время начального редактирования. Реализация может разрешить символьную ссылку от класса или интерфейса, который соединяется очень рано, даже на грани разрешения всех символьных ссылок от классов и интерфейсов, на которые далее ссылаются, рекурсивно. (Это разрешение может привести к ошибкам от дальнейшей загрузки и соединения шагов.) Этот выбор реализации представляет одно экстремальное значение и подобен виду статического редактирования, которое было сделано много лет в простых реализациях языка C.
Реализация может вместо этого хотеть разрешать символьную ссылку только, когда она фактически используется; непротиворечивое использование этой стратегии всех символьных ссылок представило бы "самую ленивую" форму разрешения. В этом случае, если Terminator
имел несколько символьных ссылок на другой класс, ссылки могли бы быть разрешены по одному или возможно нисколько, если бы эти ссылки никогда не использовались во время выполнения программы.
Единственное требование относительно того, когда разрешение выполняется, - то, что любые ошибки, обнаруженные во время разрешения, должны быть брошены в точку в программе, где некоторые меры предпринимаются программой, которая могла бы, прямо или косвенно, потребовать редактирования к классу или интерфейсу, включенному в ошибку. В "статическом" выборе реализации в качестве примера, описанном ранее, загружаясь и соединяя ошибки, мог произойти прежде, чем программа выполняется, если они включили класс или интерфейс, упомянутый в классе Terminator
или любой из далее, классы, на которые рекурсивно ссылаются, и интерфейсы. В системе, которая реализовывала "самое ленивое" разрешение, эти ошибки будут брошены только, когда символьная ссылка использовалась.
В нашем рабочем примере виртуальная машина все еще пытается выполнить метод main
из класса Terminator
. Это разрешается, только если класс был инициализирован (§2.17.4).
Инициализация состоит из выполнения любых инициализаторов переменной класса и статических инициализаторов класса Terminator
, в текстовом порядке. Но прежде Terminator
может быть инициализирован, его прямой суперкласс должен быть инициализирован, так же как прямой суперкласс его прямого суперкласса, и так далее, рекурсивно. В самом простом случае, Terminator
имеет Object
как его неявный прямой суперкласс; если класс Object
еще не был инициализирован, тогда это должно быть инициализировано прежде Terminator
инициализируется.
Если класс Terminator
имеет другой класс Super
как его суперкласс, тогда Super
должен быть инициализирован прежде Terminator
. Это требует загрузки, проверки, и подготовки Super
, если это не было уже сделано, и, в зависимости от реализации, может также включить разрешение символьных ссылок от Super
и так далее, рекурсивно.
Инициализация может таким образом вызвать загрузку, соединение, и ошибки инициализации, включая такие ошибки, включая другие типы.
Наконец, после завершения инициализации для класса Terminator
(во время которого другая последовательная загрузка, соединение, и инициализация, возможно, произошли), метод main
из Terminator
вызывается.
Class
объект представить класс или интерфейс. Двоичный формат класса или интерфейса обычно class
формат файла (см. Главу 4, "Формат файла класса"). Процесс загрузки реализуется классом ClassLoader
и его подклассы. Различные подклассы ClassLoader
может реализовать различные политики загрузки. В частности загрузчик класса может кэшировать двоичные представления классов и интерфейсов, выбрать их с упреждением основанный на ожидаемом использовании, или загрузить группу связанных классов вместе. Эти действия, возможно, не абсолютно прозрачны к рабочему приложению, если, например, недавно скомпилированная версия класса не находится, потому что более старая версия кэшируется загрузчиком класса. Это - ответственность загрузчика класса, однако, чтобы отразить загружающиеся ошибки только в точках в программе, где они, возможно, возникли, не выбирая с упреждением или групповая загрузка.
Если ошибка происходит во время загрузки класса, то экземпляр одного из следующих подклассов класса LinkageError
будет брошен в любую точку в программе, которая (прямо или косвенно) использует тип:
ClassFormatError
: Двоичные данные, который подразумевает определять требуемый скомпилированный класс или интерфейс, уродливы.
UnsupportedClassVersionError
: Класс или интерфейс не могли быть загружены, потому что это представляется, используя неподдерживаемую версию class
формат 3 файла
ClassCircularityError
: Класс или интерфейс не могли быть загружены, потому что это будет свой собственный суперкласс или суперинтерфейс (§2.13.2).
NoClassDefFoundError
: Никакое определение для требуемого класса или интерфейса не могло быть найдено соответствующим загрузчиком класса. Язык программирования Java позволяет гибкость реализации относительно того, когда соединение действий (и, из-за рекурсии, загрузка) имеют место, при условии, что семантику языка уважают, что класс или интерфейс полностью проверяются и готовятся прежде, чем это будет инициализировано, и что ошибки, обнаруженные во время редактирования, бросаются в точку в программе, где некоторые меры предпринимаются программой, которая могла бы потребовать редактирования к классу или интерфейсу, включенному в ошибку.
Например, реализация может хотеть разрешать каждую символьную ссылку в классе или взаимодействовать через интерфейс индивидуально, только когда это используется (ленивое или последнее разрешение), или разрешить их внезапно, например, в то время как класс проверяется (статическое разрешение). Это означает, что процесс разрешения может продолжаться в некоторых реализациях, после того, как класс или интерфейс был инициализирован.
Проверка гарантирует, что двоичное представление класса или интерфейса структурно корректно. Например, это проверяет, что у каждой инструкции есть допустимый код работы; то, что каждая команда перехода переходит к запуску некоторой другой инструкции, а не в середину инструкции; то, что каждому методу предоставляют структурно корректную подпись; и что каждая инструкция повинуется дисциплине типа языка программирования Java.
Если ошибка происходит во время проверки, то экземпляр следующего подкласса класса LinkageError
будет брошен в точку в программе, которая заставила класс быть проверенным:
VerifyError
: Двоичное определение для класса или интерфейса, отказавшего, чтобы передать ряд необходимых проверок, чтобы проверить, что это не может нарушить целостность виртуальной машины Java. Во время для подготовки реализации виртуальной машины Java могут предварительно вычислить дополнительные структуры данных, чтобы сделать более поздние операции на классе или интерфейсе более эффективными. Одна особенно полезная структура данных является "таблицей метода" или другой структурой данных, которая позволяет любому методу быть вызванным на экземпляры класса, не требуя поиска суперклассов во время вызова.
Двоичное представление класса или интерфейсных ссылок другие классы и интерфейсы и их поля, методы, и конструкторы символически, используя полностью определенные имена (§2.7.5) других классов и интерфейсов. Для полей и методов эти символьные ссылки включают имя класса или интерфейсного типа, который объявляет поле или метод, так же как имя поля или метода непосредственно, вместе с соответствующей информацией о типе.
Прежде, чем символьная ссылка может использоваться, она должна подвергнуться разрешению, в чем символьная ссылка проверяется и, обычно, заменяется прямой ссылкой, которая может быть более эффективно обработана, если ссылка неоднократно используется.
Если ошибка происходит во время разрешения, то экземпляр одного из следующих подклассов класса IncompatibleClassChangeError
, или некоторого другого подкласса, или IncompatibleClassChangeError
непосредственно (который является подклассом класса LinkageError
) может быть брошен в любую точку в программе, которая использует символьную ссылку на тип:
IllegalAccessError
: С символьной ссылкой встретились, который определяет использование или присвоение поля, или вызов метода, или создание экземпляра класса, к которому у кода, содержащего ссылку, нет доступа, потому что поле или метод были объявлены private
, protected
, или доступ по умолчанию (нет public
), или потому что класс не был объявлен public
. Это может произойти, например, если поле, которое первоначально объявляется public
изменяется, чтобы быть private
после того, как другой класс, который обращается к полю, был скомпилирован.
InstantiationError
: С символьной ссылкой встретились, который используется в выражении создания экземпляра класса, но экземпляр не может быть создан, потому что ссылка, оказывается, обращается к интерфейсу или к abstract
класс. Это может произойти, например, если класс, который является первоначально нет abstract
изменяется, чтобы быть abstract
после того, как другой класс, который обращается к рассматриваемому классу, был скомпилирован.
NoSuchFieldError
: С символьной ссылкой встретились, который обращается к определенному полю определенного класса или интерфейса, но класс или интерфейс не объявляют поле того имени. Это может произойти, например, если полевое объявление было удалено из класса после другого класса, который обращается к полю, был скомпилирован.
NoSuchMethodError
: С символьной ссылкой встретились, который обращается к определенному методу определенного класса или интерфейса, но класс или интерфейс не объявляют метод того имени и подписи. Это может произойти, например, если объявление метода было удалено из класса после другого класса, который обращается к методу, был скомпилирован. Перед классом или интерфейсом инициализируется, его прямой суперкласс должен быть инициализирован, но интерфейсы, реализованные классом, не должны быть инициализированы. Точно так же суперинтерфейсы интерфейсной потребности не быть инициализированными перед интерфейсом инициализируются.
Класс или интерфейсный тип T будут сразу инициализированы прежде, чем одно из следующего происходит:
final
и static
, и это инициализируется со значением константного выражения времени компиляции. Ссылка на такое поле должна быть разрешена во время компиляции к копии постоянной величины времени компиляции, таким образом, использование такого поля никогда не вызывает инициализацию. Class
и пакет java.lang.reflect
) для деталей.Намерение здесь состоит в том, что у типа есть ряд инициализаторов, которые помещают это в непротиворечивое состояние и что это состояние быть первым состоянием, которое наблюдается другими классами. Статические инициализаторы и инициализаторы переменной класса выполняются в текстовом порядке и, возможно, не обращаются к переменным класса, объявленным в классе, объявления которого появляются дословно после использования, даже при том, что эти переменные класса находятся в контексте. Это ограничение разрабатывается, чтобы обнаружить, во время компиляции, наиболее круговой или иначе уродливые инициализации.
Перед классом или интерфейсом инициализируется, его суперкласс инициализируется, если он не был ранее инициализирован.
Class
объект был уже проверен и подготовлен и что Class
объект содержит состояние, которое может указать на одну из четырех ситуаций: Class
объект проверяется и готовится, но не инициализируется.
Class
объект инициализируется некоторым определенным потоком T.
Class
объект полностью инициализируется и готов к употреблению.
Class
объект находится в ошибочном состоянии, возможно потому что отказавший шаг проверки или потому что инициализация была предпринята и отказавшей. Class
объект, который представляет класс или интерфейс, который будет инициализирован. Это включает ожидание, пока текущий поток не может получить блокировку для того объекта (§8.13).wait
на этом Class
объект (который временно выпускает блокировку). Когда текущий поток просыпается от wait
, повторите этот шаг.Class
возразите и полный обычно.Class
возразите и полный обычно.Class
объект находится в ошибочном состоянии, тогда инициализация не возможна. Выпустите блокировку на Class
объект и бросок a NoClassDefFoundError
.Class
объект теперь происходит текущим потоком, и выпустите блокировку на Class
объект.Class
объект представляет класс, а не интерфейс, и прямой суперкласс этого класса еще не был инициализирован, тогда рекурсивно выполните эту всю процедуру для неинициализированного суперкласса. Если инициализация прямого суперкласса завершается резко из-за выданного исключения, то заблокируйте это Class
объект, маркируйте это ошибочным, уведомьте все потоки ожидания, выпустите блокировку, и завершитесь резко, выдавая то же самое исключение, которое следовало из инициализации суперкласса.final
static
переменные и поля интерфейсов, значения которых являются константами времени компиляции, инициализируются сначала.Class
объект, маркируйте, он полностью инициализировал, уведомьте все потоки ожидания, выпустите блокировку, и обычно завершайте эту процедуру.Error
или один из его подклассов, затем создайте новый экземпляр класса ExceptionInInitializerError
, с E как параметр, и использование этот объект вместо E в следующем шаге. Но если новый экземпляр ExceptionInInitializerError
не может быть создан потому что OutOfMemoryError
происходит, тогда вместо этого используйте OutOfMemoryError
объект вместо E в следующем шаге.Class
объект, маркируйте это ошибочным, уведомьте все потоки ожидания, выпустите блокировку, и завершите эту процедуру резко с причиной E или ее заменой как определено в предыдущем шаге. ExceptionInInitializerError
как описано здесь.
newInstance
метод класса Class
создает новый экземпляр класса, представленного Class
объект, для которого был вызван метод. String
литерал может создать новое String
объект (§2.4.8), чтобы представить тот литерал. Это, возможно, не происходит если a String
объект был уже создан, чтобы представить предыдущее возникновение того литерала, или если String.intern
метод был вызван на a String
объект, представляющий ту же самую строку как литерал.
String
объект представить результат. Операторы конкатенации строк могут также создать временные объекты обертки для значения типа примитива (§2.4.1). Всякий раз, когда новый экземпляр класса создается, место в памяти выделяется для него с комнатой для всех переменных экземпляра, объявленных в типе класса и всех переменных экземпляра, объявленных в каждом суперклассе типа класса, включая все переменные экземпляра, которые могут быть скрыты. Если нет достаточного пространства, доступного, чтобы выделить память для объекта, то создание экземпляра класса завершается резко с OutOfMemoryError
. Иначе, все переменные экземпляра в новом объекте, включая объявленных в суперклассах, инициализируются к их значениям по умолчанию (§2.5.1).
Непосредственно перед тем, как ссылка на недавно создаваемый объект возвращается как результат, обозначенный конструктор обрабатывается, чтобы инициализировать новый объект, используя следующую процедуру:
this
), затем оцените параметры и обработайте тот вызов конструктора, рекурсивно используя эти те же самые пять шагов. Если тот вызов конструктора завершается резко, то эта процедура завершается резко по той же самой причине. Иначе, продолжайте с шагом 5.this
) и находится в классе кроме Object
, тогда этот конструктор начнет с явного или неявного вызова конструктора суперкласса (использование super
). Оцените параметры и обработайте тот вызов конструктора суперкласса, рекурсивно используя эти те же самые пять шагов. Если тот вызов конструктора завершается резко, то эта процедура завершается резко по той же самой причине. Иначе, продолжайте с шагом 4.Object
имеет a protected
метод вызывают finalize
; этот метод может быть переопределен другими классами. Определенное определение finalize
это может быть вызвано для объекта, вызывается финализатором того объекта. Прежде, чем хранение для объекта исправляется сборщиком "мусора", виртуальная машина Java вызовет финализатор того объекта. Финализаторы обеспечивают шанс освободить ресурсы (такие как дескрипторы файлов или контексты графики операционной системы), который не может быть освобожден автоматически автоматическим менеджером по хранению. В таких ситуациях, просто исправляя память, используемую объектом, не гарантировал бы, что ресурсы, которые она содержала, будут исправлены.
Язык программирования Java не определяет, как скоро финализатор будет вызван, кроме сказать, что это произойдет прежде, чем хранение для объекта снова используется. И при этом язык не определяет, какой поток вызовет финализатор для любого данного объекта. Если непойманное исключение выдается во время завершения, исключение игнорируется, и завершение того объекта завершается.
finalize
метод объявляется в классе Object
не предпринимает мер. Однако, факт тот класс Object
объявляет a finalize
метод означает что finalize
метод для любого класса может всегда вызывать finalize
метод для его суперкласса, который является обычно хорошей практикой. (В отличие от конструкторов, финализаторы автоматически не вызывают финализатор для суперкласса; такой вызов должен быть кодирован явно.)
Для эффективности реализация может отследить классы, которые не переопределяют finalize
метод класса Object
или то переопределение это тривиальным способом, такой как
protected void finalize() { super.finalize(); }Мы поощряем реализации обрабатывать такие объекты как наличие финализатора, который не переопределяется и завершить их более эффективно.
finalize
метод может быть вызван явно, точно так же как любой другой метод. Однако, выполнение так не имеет никакого эффекта на возможное автоматическое завершение объекта.
Виртуальная машина Java не налагает упорядочивания на finalize
вызовы метода. Финализаторы можно вызвать в любом порядке или даже одновременно.
Как пример, если циркулярная соединенная группа незавершенных объектов становится недостижимой, то все объекты могут стать finalizable вместе. В конечном счете финализаторы для этих объектов могут быть вызваны в любом порядке или даже одновременно использовании многократных потоков. Если автоматический менеджер по хранению позже находит, что объекты недостижимы, то их хранение может быть исправлено.
exit
метод класса Runtime
или класс System
, и работа выхода разрешается менеджером безопасности. runFinalizersOnExit
из класса System
с параметром true
.4 Финализаторами по умолчанию не выполняются на выходе. Однажды рабочие финализаторы на выходе был включен, он может быть отключен, вызывая runFinalizersOnExit
с параметром false
. Вызов runFinalizersOnExit
метод разрешается, только если вызывающей стороне позволяют exit
и иначе отклоняется менеджером безопасности. Каждое константное выражение времени компиляции строго FP. Если выражение не является константным выражением времени компиляции, то рассмотрите все объявления класса, интерфейсные объявления, и объявления метода, которые содержат выражение. Если какое-либо такое объявление переносит strictfp модификатор, то выражение строго FP.
Из этого следует, что выражение не строго FP, если и только если это не константное выражение времени компиляции, и это не появляется в пределах никакого объявления, у которого есть strictfp модификатор.
В пределах строгого FP выражения все промежуточные значения должны быть элементами набора значений плавающего или двойного набора значений, подразумевая, что результаты всех строгих FP выражений должны быть предсказанными арифметикой IEEE 754 на операндах, представленных, используя единственные и двойные форматы. В пределах выражения, которое не строго FP, некоторый дрейф предоставляют для реализации использовать расширенный диапазон экспоненты, чтобы представить промежуточные результаты; результирующий эффект, примерно разговор, состоит в том, что вычисление могло бы произвести "корректный ответ" в ситуациях, где монопольное использование набора значений плавающего или удваивается, набор значений мог бы привести к переполнению или потере значимости.
Любой поток может быть отмечен как поток демона. Когда код, работающий в некотором потоке, создает новое Thread
объект, тот новый поток первоначально отмечается как поток демона, если и только если поток создания является потоком демона. Программа может измениться, является ли определенный поток потоком демона, вызывая setDaemon
метод в классе Thread
. Виртуальная машина Java первоначально запускает с единственным потоком недемона, который обычно вызывает метод main
из некоторого класса. Виртуальная машина может также создать другие потоки демона во внутренних целях. Виртуальная машина Java выходит, когда все потоки недемона завершились (§2.17.9).
Обеспечивая механизмы для того, чтобы они синхронизировали параллельное действие потоков, язык программирования Java поддерживает кодирование программ, которые, хотя параллельный, все еще показывают детерминированное поведение. Чтобы синхронизировать потоки, язык использует мониторы, механизм для того, чтобы позволить одному потоку за один раз выполнять область кода. Поведение мониторов объясняется с точки зрения блокировок. Есть блокировка, связанная с каждым объектом.
synchronized
оператор выполняет два специальных действия, относящиеся только к многопоточной работе:
synchronized
; такой метод ведет себя, как будто его тело содержалось в a synchronized
оператор. wait
, notify
, и notifyAll
из класса Object
поддерживайте эффективную передачу управления от одного потока до другого. Вместо того, чтобы просто "вращаться" (неоднократно блокировка и разблокирование объекта видеть, изменилось ли некоторое внутреннее состояние), который использует вычислительное усилие, поток может приостановить себя использование wait
до тех пор, пока другой поток пробуждает это использование notify
или notifyAll
. Это является особенно соответствующим в ситуациях, где у потоков есть отношение производителя-потребителя (активно сотрудничающий на общей цели), а не отношение взаимного исключения (пытающийся избежать конфликтов, совместно используя общий ресурс).Поскольку поток выполняет код, он выполняет последовательность действий. Поток может использовать значение переменной или присвоить его новое значение. (Другие действия включают арифметические операции, условные тесты, и вызовы метода, но они не включают переменные непосредственно.), Если два или больше параллельных действия потоков на совместно используемой переменной, есть возможность, что действия на переменной приведут к зависимым от синхронизации результатам. Эта зависимость от синхронизации свойственна от параллельного программирования и производит одну из немногих ситуаций, где результат программы не определяется исключительно Спецификацией языка JavaTM.
У каждого потока есть рабочая память, в которой он может сохранить копии значений переменных от основной памяти, которые совместно используются всеми потоками. Чтобы получить доступ к совместно используемой переменной, поток обычно сначала получает блокировку и сбрасывает ее рабочую память. Это гарантирует, что совместно использованные значения будут после того загружены от совместно используемой основной памяти до рабочей памяти потока. Разблокировав блокировку, поток гарантирует, что значения, сохраненные потоком в его рабочей памяти, будут записаны обратно к основной памяти.
Взаимодействие потоков с основной памятью, и таким образом друг с другом, может быть объяснено с точки зрения определенных низкоуровневых действий. Есть правила о порядке, в котором могут произойти эти действия. Эти правила налагают ограничения на любую реализацию языка программирования Java. Программист может положиться на правила предсказать возможные поведения параллельной программы. Правила действительно, однако, преднамеренно дают конструктору определенные свободы. Намерение состоит в том, чтобы разрешить аппаратные и программные методы определенного стандарта, которые могут значительно улучшить скорость и эффективность параллельного кода.
Кратко помещенный, важными последствиями правил является следующее:
long
и double
значения; см. §8.4.)
http://java.sun.com
.2 Примечания, что локальная переменная не инициализируется на ее создании и, как полагают, содержит значение только, как только это присваивается (§2.5.1).
3
UnsupportedClassVersionError
, подкласс ClassFormatError
, был представлен в Java 2 платформы, v1.2, чтобы включить легкой идентификации a ClassFormatError
вызванный попыткой загрузить класс представлял использование неподдерживаемой версии class
формат файла.
4 метод runFinalizersOnExit
был сначала реализован в выпуске 1.1 JDK, но был осужден в Java 2 платформы, v1.2.
Содержание | Предыдущий | Следующий | Индекс
Спецификация Виртуальной машины JavaTM
Авторское право © Sun Microsystems, Inc 1999 года. Все права защищены
Пожалуйста, отправьте любые комментарии или исправления к jvm@java.sun.com