![]() |
Spec-Zone .ru
спецификации, руководства, описания, API
|
Содержание | Предыдущий | Следующий | Индекс | Спецификация языка Java Третий Выпуск |
ГЛАВА 6
Имена используются, чтобы обратиться к объектам, объявленным в программе. Объявленный объект (§6.1) является пакетом, тип класса (нормальный или перечислимый), интерфейсный тип (нормальный или тип аннотации), элемент (класс, интерфейс, поле, или метод) ссылочного типа, введите параметр (класса, интерфейса, метода или конструктора) (§4.4), параметр (к методу, конструктору, или обработчику исключений), или локальная переменная.
Имена в программах или просты, состоя из единственного идентификатора, или квалифицированный, состоя из последовательности идентификаторов, разделенных".
"маркеры (§6.2).
У каждого объявления, которое представляет имя, есть контекст (§6.3), который является частью текста программы, в пределах которого объявленный объект может быть упомянут простым именем.
У пакетов и ссылочных типов (то есть, типы классов, интерфейсные типы, и типы массива) есть элементы (§6.4). Элемент может быть отнесен в использование полностью определенного имени N.x, где N является простым или полностью определенным именем, и x является идентификатором. Если N называет пакет, то x является элементом того пакета, который является или классом или интерфейсным типом или подпакетом. Если N называет ссылочный тип или переменную ссылочного типа, то x называет элемент того типа, который является или классом, интерфейсом, полем, или методом.
В определении значения имени (§6.5), контекст возникновения используется, чтобы снять неоднозначность среди пакетов, типов, переменных, и методов с тем же самым именем.
Управление доступом (§6.6) может быть определено в классе, интерфейсе, методе, или полевом объявлении, чтобы управлять, когда доступ к элементу предоставляется. Доступ является различным понятием от контекста; доступ определяет часть текста программы, в пределах которого объявленный объект может быть упомянут полностью определенным именем, выражение доступа к полю (§15.11), или выражение вызова метода (§15.12), в котором метод не определяется простым именем. Доступ по умолчанию - то, что к элементу можно получить доступ где угодно в пределах пакета, который содержит его объявление; другие возможности public
, protected
, и private
.
Полностью определенные и канонические имена (§6.7) и соглашения о присвоении имен (§6.8) также обсуждаются в этой главе.
Имя поля, параметра, или локальной переменной может использоваться в качестве выражения (§15.14.2). Имя метода может появиться в выражении только как часть выражения вызова метода (§15.12). Имя класса или интерфейсного типа может появиться в выражении только как часть литерала класса (§15.8.2), квалифицированный это выражение (§15.8.4), выражение создания экземпляра класса (§15.9), выражение создания массива (§15.10), выражение броска (§15.16), instanceof
выражение (§15.20.2), перечислимая константа (§8.9), или как часть полностью определенного имени для поля или метода. Имя пакета может появиться в выражении только как часть полностью определенного имени для класса или соединить интерфейсом с типом.
package
объявление (§7.4)
length
, который является неявно элементом каждого типа массива (§10.7)
abstract
метод интерфейса (§9.4)
catch
пункт a try
оператор (§14.20)
Есть две формы имен: простые имена и полностью определенные имена. Простое имя является единственным идентификатором. Полностью определенное имя состоит из имени,".
"маркер, и идентификатор.
В определении значения имени (§6.5), принимается во внимание контекст, в котором появляется имя. Правила §6.5 различают среди контекстов, где имя должно обозначить (обратитесь к), пакет (§6.5.3), тип (§6.5.5), переменная или значение в выражении (§6.5.6), или метод (§6.5.7).
Не все идентификаторы в программах являются частью имени. Идентификаторы также используются в следующих ситуациях:
.
"маркер, чтобы указать на элемент объекта, который является значением выражения или ключевого слова super
это появляется перед".
"маркер
.
"маркер и перед"(
"маркер, чтобы указать на метод, который будет вызван для объекта, который является значением выражения или ключевого слова super
это появляется перед".
"маркер
break
(§14.15) и continue
операторы (§14.16), которые обращаются к меткам оператора.
идентификаторыclass Test { public static void main(String[] args) { Class c = System.out.getClass(); System.out.println(c.toString().length() + args[0].length() + args.length); } }
Test
, main
, и первые возникновения args
и c
не имена; скорее они используются в объявлениях, чтобы определить имена объявленных объектов. Имена String
, Class
, System.out.getClass
, System.out.println
, c.toString
, args
, и args.length
появитесь в примере. Первое возникновение length
не имя, а скорее идентификатор, появляющийся в выражении вызова метода (§15.12). Второе возникновение length
не имя, а скорее идентификатор, появляющийся в выражении вызова метода (§15.12).Идентификаторы, используемые в помеченных операторах и их связанном break
и continue
операторы являются абсолютно отдельными от используемых в объявлениях. Таким образом следующий код допустим:
Этот код был взят от версии классаclass TestString { char[] value; int offset, count; int indexOf(TestString str, int fromIndex) { char[] v1 = value, v2 = str.value; int max = offset + (count - str.count); int start = offset + ((fromIndex < 0) ? 0 : fromIndex); i: for (int i = start; i <= max; i++) { int n = str.count, j = i, k = str.offset; while (n-- != 0) { if (v1[j++] != v2[k++]) continue i; } return i - offset; } return -1; } }
String
и его метод indexOf
, где метку первоначально вызвали test
. Изменение метки, чтобы иметь то же самое имя как локальная переменная i
не затеняет (§6.3.2) метку в пределах объявления i
. Идентификатор max
возможно, также использовался в качестве метки оператора; метка не затенила бы локальную переменную max
в пределах помеченного оператора.Правила обзора данных для различных конструкций даются в разделах, которые описывают те конструкции. Для удобства правила повторяются здесь:
Контекст объявления заметного (§7.4.3) высокоуровневого пакета является всеми заметными единицами компиляции (§7.3). Объявление пакета, который не заметен, никогда не находится в контексте. Объявления подпакета никогда не находятся в контексте.
Контекст типа, импортированного объявлением единственного импорта типа (§7.5.1) или объявлением "импорт типа по требованию" (§7.5.2), является всем классом и интерфейсными описаниями типа (§7.6) в единице компиляции, в которой появляется объявление импорта.
Контекст элемента, импортированного объявлением единственного статического импорта (§7.5.3) или объявлением "статический импорт по требованию" (§7.5.4), является всем классом и интерфейсными описаниями типа (§7.6) в единице компиляции, в которой появляется объявление импорта.
Контекст высокоуровневого типа является всеми описаниями типа в пакете, в котором объявляется высокоуровневый тип.
Контекст объявления элемента м. объявил в или наследовался типом класса C, все тело C, включая любые объявления вложенного типа.
Контекст объявления элемента м. объявил в или наследовался интерфейсным типом, я - все тело меня, включая любые объявления вложенного типа.
Контекст параметра метода (§8.4.1) или конструктор (§8.8.1) является всем телом метода или конструктора.
Контекст параметра типа интерфейса является всем объявлением интерфейса включая раздел параметра типа непосредственно. Поэтому, введите параметры, может появиться как части их собственных границ, или как границы других параметров типа, объявленных в том же самом разделе.
Контекст параметра типа метода является всем объявлением метода, включая раздел параметра типа непосредственно. Поэтому, введите параметры, может появиться как части их собственных границ, или как границы других параметров типа, объявленных в том же самом разделе.
Контекст параметра типа конструктора является всем объявлением конструктора, включая раздел параметра типа непосредственно. Поэтому, введите параметры, может появиться как части их собственных границ, или как границы других параметров типа, объявленных в том же самом разделе.
Контекст объявления локальной переменной в блоке (§14.4.2) является остальной частью блока, в котором объявление появляется, запускаясь с его собственного инициализатора (§14.4) и включая дальнейшие операторы объявления направо в операторе объявления локальной переменной.
Контекст локального класса, сразу включенного блоком (§14.2), является остальной частью сразу блока включения, включая его собственное объявление класса. Контекст локального класса, сразу включенного в группе оператора блока переключателя (§14.11), является остальной частью сразу группы оператора блока переключателя включения, включая ее собственное объявление класса.
Контекст локальной переменной объявляется в forInit части основного for
оператор (§14.14) включает все следующее:
for
оператор
for
оператор
for
оператором (§14.14) является содержавший Оператор
Контекст параметра обработчика исключений, который объявляется в a catch
пункт a try
оператор (§14.20) является всем блоком, связанным с catch
.
Эти правила подразумевают, что объявления класса и интерфейсных типов не должны появиться перед использованием типов.
В примере:
package points; class Point { int x, y; PointList list; Point next; } class PointList { Point first; }
использование PointList
в классе Point
корректно, потому что контекст объявления класса PointList
включает оба класса Point
и класс PointList
, так же как любые другие описания типа в других единицах компиляции пакета points
.
Объявление d типа, названного n тенями объявления любых других типов, названных n, которые находятся в контексте в точке, где d происходит всюду по контексту d.
Объявление d поля, локальной переменной, параметра метода, параметра конструктора или параметра обработчика исключений, названного n тенями объявления любых других полей, локальных переменных, параметров метода, параметров конструктора или параметров обработчика исключений, названных n, которые находятся в контексте в точке, где d происходит всюду по контексту d.
Объявление d метода, названного n тенями объявления любых других методов, названных n, которые находятся в контексте включения в точке, где d происходит всюду по контексту d.
Объявление пакета никогда тени любое другое объявление.
Объявление d единственного импорта типа в единице компиляции c пакета p, который импортирует тип, названный n тенями объявления:
Объявление d единственного статического импорта в единице компиляции c пакета p, который импортирует поле, названное n тенями объявление любого статического поля, названного n, импортированным объявлением "статический импорт по требованию" в c, всюду по c.
Объявление d единственного статического импорта в единице компиляции c пакета p, который импортирует метод, названный n с тенями подписи s объявление любого статического метода, названного n с подписью s, импортированной объявлением "статический импорт по требованию" в c, всюду по c.
Объявление d единственного статического импорта в единице компиляции c пакета p, который импортирует тип, названный n тенями объявления:
Объявление "импорт типа по требованию" никогда не заставляет никакое другое объявление быть затененным.
Объявление "статический импорт по требованию" никогда не заставляет никакое другое объявление быть затененным.
Объявление d, как говорят, видимо в точке p в программе, если контекст d включает p, и d не затенен любым другим объявлением в p. Когда момент программы, который мы обсуждаем, будет четким от контекста, мы будем часто просто говорить, что объявление видимо.
Отметьте, что затенение отлично от сокрытия (§8.3, §8.4.8.2, §8.5, §9.3, §9.5). Сокрытие, в техническом смысле, определенном в этой спецификации, применяется только к элементам, которые были бы иначе наследованы, но являются не из-за объявления в подклассе. Затенение также отлично от затемнения (§6.3.2).
Вот пример затенения полевого объявления объявлением локальной переменной:
производит вывод:class Test { static int x = 1; public static void main(String[] args) { int x = 0; System.out.print("x=" + x); System.out.println(", Test.x=" + Test.x); } }
Этот пример объявляет:x=0, Test.x=1
Test
static
) переменная x
это - элемент класса Test
main
это - элемент класса Test
args
из main
метод.
x
из main
метод
Так как контекст переменной класса включает все тело класса (§8.2) переменная класса x
обычно было бы доступно всюду по всему телу метода main
. В этом примере, однако, переменной класса x
затенено в пределах тела метода main
объявлением локальной переменной x
.
Локальная переменная имеет как ее остальная часть контекста блока, в котором она объявляется (§14.4.2); в этом случае это - остальная часть тела main
метод, а именно, его инициализатор"0
"и вызовы print
и println
.
Это означает что:
x
"в вызове print
обращается к (обозначает) значение локальной переменной x
.
println
использует полностью определенное имя (§6.6) Test.x
, который использует имя типа класса Test
получить доступ к переменной класса x
, потому что объявление Test.x
затенено в этой точке и не может быть упомянут ее простым именем. Следующий пример иллюстрирует затенение одного описания типа другим:
компиляции и печатные издания:import java.util.*; class Vector { int val[] = { 1 , 2 };}
class Test { public static void main(String[] args) { Vector v = new Vector(); System.out.println(v.val[0]); } }
использование класса1
Vector
объявленный здесь в предпочтении к универсальному (§8.1.2) классу java.util.Vector
это могло бы быть импортировано по требованию.Затемнение отлично от затенения (§6.3.1) и скрывающийся (§8.3, §8.4.8.2, §8.5, §9.3, §9.5). Соглашения о присвоении имен §6.8 помогают уменьшить затемнение.
Этот раздел обеспечивает краткий обзор элементов пакетов и ссылочных типов здесь как фон для обсуждения полностью определенных имен и определения значения имен. Для полного описания членства см. §4.4, §4.5.2, §4.8, §4.9, §7.1, §8.2, §9.2, и §10.7.
Элементы пакета являются его подпакетами и всем верхним уровнем (§7.6) типы классов (§8) и высокоуровневые типы интерфейса (§9) объявленный во всех единицах компиляции (§7.3) пакета.
Вообще, подпакеты пакета определяются хост-системой (§7.2). Однако, пакет java
всегда включает подпакеты lang
и io
и может включать другие подпакеты. Ни у каких двух отличных элементов того же самого пакета не может быть того же самого простого имени (§7.1), но у элементов различных пакетов может быть то же самое простое имя.
Например, возможно объявить пакет:
это имеет как элемент apackage vector; public class Vector { Object[] vec; }
public
класс называют Vector
, даже при том, что пакет java.util
также объявляет названный класс Vector
. Эти два типов классов отличаются, отражаются фактом, что у них есть различные полностью определенные имена (§6.7). Полностью определенное имя этого примера Vector
vector.Vector
, тогда как java.util.Vector
полностью определенное имя Vector
класс обычно включается в платформу Java. Поскольку пакет vector
содержит названный класс Vector
, этому нельзя было также назвать подпакет Vector
.Элементы типа класса являются всем следующим:
Object
не имеет никакого прямого суперкласса),
Нет никакого ограничения против поля и метода типа класса, имеющего то же самое простое имя. Аналогично, нет никакого ограничения против задействованного класса или задействованного интерфейса типа класса, имеющего то же самое простое имя как поле или метод того типа класса.
У класса может быть два или больше поля с тем же самым простым именем, если они объявлены в различных интерфейсах и наследованы. Попытка обратиться к любому из полей ее простым именем приводит к ошибке времени компиляции (§6.5.7.2, §8.2).
В примере:
имяinterface Colors { int WHITE = 0, BLACK = 1; } interface Separates { int CYAN = 0, MAGENTA = 1, YELLOW = 2, BLACK = 3; } class Test implements Colors, Separates { public static void main(String[] args) { System.out.println(BLACK); // compile-time error: ambiguous } }
BLACK
в методе main
неоднозначно, потому что класс Test
имеет два названные элемента BLACK
, один наследованный от Colors
и один от Separates
.У типа класса может быть два или больше метода с тем же самым простым именем, если у методов есть подписи, которые не эквивалентны переопределению (§8.4.2). Такое имя элемента метода, как говорят, перегружается.
Тип класса может содержать объявление для метода с тем же самым именем и той же самой подписью как метод, который был бы иначе наследован от суперкласса или суперинтерфейса. В этом случае метод суперкласса или суперинтерфейса не наследован. Если метод, не наследованный, abstract
, тогда новое объявление, как говорят, реализует это; если метод, не наследованный, не abstract
, тогда новое объявление, как говорят, переопределяет это.
В примере:
классclass Point { float x, y; void move(int dx, int dy) { x += dx; y += dy; } void move(float dx, float dy) { x += dx; y += dy; } public String toString() { return "("+x+","+y+")"; } }
Point
имеет два элемента, которые являются методами с тем же самым именем, move
. Перегруженный move
метод класса Point
выбранный для любого определенного вызова метода определяется во время компиляции перегружающейся процедурой разрешения, данной в §15.12.В этом примере, элементах класса Point
float
переменные экземпляра x
и y
объявленный в Point
, эти объявленные два move
методы, объявленный toString
метод, и элементы это Point
наследовался от его неявного прямого суперкласса Object
(§4.3.2), такой как метод hashCode
. Отметьте это Point
не наследовался toString
метод класса Object
потому что тот метод переопределяется объявлением toString
метод в классе Point
.
throws
пункт t, соответствующий каждому общедоступному методу экземпляра м. с подписью s, возвратите тип r, и throws
пункт t, объявленный в Object
, если метод с той же самой подписью, тем же самым типом возврата, и совместимым throws
пункт явно объявляется интерфейсом. Это - ошибка времени компиляции, если интерфейс явно объявляет такой метод м. в случае, где м., как объявляют, находится final
в Object
. У интерфейса может быть два или больше поля с тем же самым простым именем, если они объявлены в различных интерфейсах и наследованы. Попытка обратиться к любому такому полю его простым именем приводит к ошибке времени компиляции (§6.5.6.1, §9.2).
В примере:
элементы интерфейсаinterface Colors { int WHITE = 0, BLACK = 1; } interface Separates { int CYAN = 0, MAGENTA = 1, YELLOW = 2, BLACK = 3; } interface ColorsAndSeparates extends Colors, Separates { int DEFAULT = BLACK; // compile-time error: ambiguous }
ColorsAndSeparates
включайте те элементы, наследованные от Colors
и наследованные от Separates
, а именно, WHITE
, BLACK
(сначала два), CYAN
, MAGENTA
, YELLOW
, и BLACK
(второй из два). Имя элемента BLACK
неоднозначно в интерфейсе ColorsAndSeparates
.Элементы типа массива являются всем следующим:
public
final
поле length
, который содержит число компонентов массива (length
может быть положительным или нуль).
public
метод clone
, который переопределяет метод того же самого имени в классе Object
и не выдает проверенных исключений. Тип возврата метода клона типа T массива [] является T [].
Object
; единственный метод Object
это не наследовано, clone
метод.
производит вывод:class Test { public static void main(String[] args) { int[] ia = new int[3]; int[] ib = new int[6]; System.out.println(ia.getClass() == ib.getClass()); System.out.println("ia has length=" + ia.length); } }
Этот пример использует методtrue ia has length=3
getClass
унаследованный от класса Object
и поле length
. Результат сравнения Class
объекты в первом println
демонстрирует, что все массивы, компоненты которых имеют тип int
экземпляры того же самого типа массива, который является int[]
.
PackageName: Identifier PackageName . Identifier TypeName: Identifier PackageOrTypeName . Identifier ExpressionName: Identifier AmbiguousName . Identifier MethodName: Identifier AmbiguousName . Identifier PackageOrTypeName: Identifier PackageOrTypeName . Identifier AmbiguousName: Identifier AmbiguousName . Identifier
Использование контекста помогает минимизировать конфликты имен между объектами различных видов. Такие конфликты будут редки, если соглашения о присвоении имен, описанные в §6.8, будут сопровождаться. Однако, конфликты могут возникнуть неумышленно как типы, разработанные различными программистами, или различные организации развиваются. Например, у типов, методов, и полей может быть то же самое имя. Всегда возможно различить метод и поле с тем же самым именем, так как контекст использования всегда говорит, предназначается ли метод.
.
"в квалифицированном PackageName
extends
пункт в объявлении переменной типа (§8.1.2)
extends
пункт подстановочного знака вводит параметр (§4.5.1)
super
пункт подстановочного знака вводит параметр (§4.5.1)
extends
пункт в объявлении класса (§8.1.4)
implements
пункт в объявлении класса (§8.1.5)
extends
пункт в интерфейсном объявлении (§9.1.3)
catch
пункт a try
оператор (§14.20)
this
выражение (§15.8.4).
super
(§15.11.2)
super
(§15.12)
instanceof
оператор отношения (§15.20.2)
Имя синтаксически классифицируется как ExpressionName в этих контекстах:
(
"в выражении вызова метода (§15.12)
.
"в квалифицированном ExpressionName
.
"в квалифицированном MethodName
.
"в квалифицированном AmbiguousName
.
", и Идентификатор, тогда имя налево от".
"сначала повторно классифицируется, поскольку это - самостоятельно AmbiguousName. Есть тогда выбор: .
"повторно классифицируется как PackageName, затем если есть пакет, имя которого является именем налево от".
"и тот пакет содержит объявление типа, имя которого является тем же самым как Идентификатором, тогда этот AmbiguousName повторно классифицируется как TypeName. Иначе, этот AmbiguousName повторно классифицируется как PackageName. Более поздний шаг определяет, существует ли пакет того имени фактически.
.
"повторно классифицируется как TypeName, затем если Идентификатор является именем метода или полем типа, обозначенного TypeName, этот AmbiguousName повторно классифицируется как ExpressionName. Иначе, если Идентификатор является именем типа элемента типа, обозначенного TypeName, этот AmbiguousName повторно классифицируется как TypeName. Иначе, ошибка времени компиляции заканчивается.
.
"повторно классифицируется как ExpressionName, затем позвольте T быть типом выражения, обозначенного ExpressionName. Если Идентификатор является именем метода или полем типа, обозначенного T, этот AmbiguousName повторно классифицируется как ExpressionName. Иначе, если Идентификатор является именем типа элемента (§8.5, §9.5) типа, обозначенного T, то этот AmbiguousName повторно классифицируется как TypeName. Иначе, ошибка времени компиляции заканчивается.
Как пример, рассмотрите следующий изобретенный "код библиотеки":
и затем рассмотрите этот пример кода в другом пакете:package org.rpgpoet; import java.util.Random; interface Music { Random[] wizards = new Random[4]; }
Прежде всего, имяpackage bazola; class Gabriel { static int n = org.rpgpoet.Music.wizards.length; }
org.rpgpoet.Music.wizards.length
классифицируется как ExpressionName, потому что он функционирует как PostfixExpression. Поэтому, каждое из имен:
первоначально классифицируется как AmbiguousName. Они тогда повторно классифицируются:org.rpgpoet.Music.wizards org.rpgpoet.Music org.rpgpoet org
rpgpoet
в любой единице компиляции пакета org (и мы знаем, что нет такого класса или интерфейса, потому что пакету org назвали подпакет rpgpoet
), полностью определенное имя org.rpgpoet
повторно классифицируется как PackageName.
org.rpgpoet
имеет интерфейсный названный тип Music
, полностью определенное имя org.rpgpoet.Music
повторно классифицируется как TypeName.
org.rpgpoet.Music
TypeName, полностью определенное имя org.rpgpoet.Music.wizards
повторно классифицируется как ExpressionName. .
Идентификатор, тогда Q должен также быть именем пакета. Имя Q пакета.
Идентификатор называет пакет, который является элементом под названием Идентификатор в пределах пакета, названного Q. Если Q не называет заметный пакет (§7.4.3), или Идентификатор не является простым именем заметный подпакет того пакета, то ошибка времени компиляции происходит.Иначе, PackageOrTypeName повторно классифицируется как PackageName. Значение PackageOrTypeName является значением повторно классифицированного имени.
Иначе, это повторно классифицируется как PackageName. Значение квалифицированного PackageOrTypeName является значением повторно классифицированного имени.
.
Идентификатор, тогда Q должен быть или именем типа или именем пакета. Если Идентификатор называет точно один тип, который является элементом типа или пакета, обозначенного Q, то квалифицированное имя типа обозначает тот тип. Если Идентификатор не называет тип элемента (§8.5, §9.5) в пределах Q, или тип элемента под названием Идентификатор в пределах Q не доступен (§6.6), или Идентификатор называет больше чем один тип элемента в пределах Q, то ошибка времени компиляции происходит. Пример:
произведенный следующий вывод в первый раз это было выполнено:package wnj.test; class Test { public static void main(String[] args) { java.util.Date date = new java.util.Date(System.currentTimeMillis()); System.out.println(date.toLocaleString()); } }
В этом примере имяSun Jan 21 22:56:29 1996
java.util.Date
должен обозначить тип, таким образом, мы сначала используем процедуру рекурсивно, чтобы определить если java.util
доступный тип или пакет, который это, и затем надейтесь видеть если тип Date
доступно в этом пакете.
Обсуждение
Имена типов отличны от спецификаторов описания типа (§4.3). Имя типа всегда квалифицируется meas другого имени типа. В некоторых случаях необходимо получить доступ к внутреннему классу, который является элементом параметризованного типа:
Если мы получили доступclass GenericOuter<T extends Number> { public class Inner<S extends Comparable<S>> { T getT() { return null;} S getS() { return null;} } }; GenericOuter<Integer>.Inner<Double> x1 = null; Integer i = x1.getT(); Double d = x1.getS();
Inner
квалифицируя это с именем типа, как в:
мы вызвали бы его использование в качестве необработанного типа, теряя информацию о типе.GenericOuter.Inner x2 = null;
Если объявление объявляет заключительное поле, значение имени является значением того поля. Иначе, значение имени выражения является переменной, объявленной объявлением.
Если поле является переменной экземпляра (§8.3), имя выражения должно появиться в пределах объявления метода экземпляра (§8.4), конструктор (§8.8), инициализатор экземпляра (§8.6), или инициализатор переменной экземпляра (§8.3.2.2). Если это появляется в пределах a static
метод (§8.4.3.2), статический инициализатор (§8.7), или инициализатор для a static
переменная (§8.3.2.1, §12.4.2), затем ошибка времени компиляции происходит.
Тип имени выражения является объявленным типом поля, локальной переменной или параметра после преобразования получения (§5.1.10).
имена, используемые в качестве левых сторон в присвоениях наclass Test { static int v; static final int f = 3; public static void main(String[] args) { int i; i = 1; v = 2; f = 33; // compile-time error System.out.println(i + " " + v + " " + f); } }
i
, v
, и f
обозначьте локальную переменную i
, поле v
, и значение f
(не переменная f
, потому что f
a final
переменная). Пример поэтому производит ошибку во время компиляции, потому что у последнего присвоения нет переменной как ее левой стороны. Если ошибочное присвоение удаляется, измененный код может быть скомпилирован, и это произведет вывод:
1 2 3
.
Идентификатор, тогда Q был уже классифицирован как имя пакета, имя типа, или имя выражения:
static
), затем ошибка времени компиляции происходит.
final
, тогда Q.
Идентификатор обозначает значение переменной класса. Тип выражения Q.
Идентификатор является объявленным типом переменной класса после преобразования получения (§5.1.10). Если Q.
Идентификатор появляется в контексте, который требует переменной и не значения, затем ошибка времени компиляции происходит.
.
Идентификатор обозначает переменную класса. Тип выражения Q.
Идентификатор является объявленным типом переменной класса после преобразования получения (§5.1.10). Отметьте, что этот пункт касается использования перечислимых констант (§8.9), так как у них всегда есть соответствие final
переменная класса. .
Идентификатор обозначает значение поля. Тип выражения Q.
Идентификатор является объявленным типом поля после преобразования получения (§5.1.10). Если Q.
Идентификатор появляется в контексте, который требует переменной и не значения, затем ошибка времени компиляции происходит. final
поле типа класса (который может быть или переменной класса или переменной экземпляра),
final
поле length
из типа массива
тогда Q.
Идентификатор обозначает значение поля. Тип выражения Q.
Идентификатор является объявленным типом поля после преобразования получения (§5.1.10). Если Q.
Идентификатор появляется в контексте, который требует переменной и не значения, затем ошибка времени компиляции происходит.
.
Идентификатор обозначает переменную, поле Id класса T, который может быть или переменной класса или переменной экземпляра. Тип выражения Q.
Идентификатор является типом члена поля после преобразования получения (§5.1.10). Пример:
встречается с двумя ошибками времени компиляции, потому чтоclass Point { int x, y; static int nPoints; } class Test { public static void main(String[] args) { int i = 0; i.x++; // compile-time error Point p = new Point(); p.nPoints(); // compile-time error } }
int
переменная i
не имеет никаких элементов, и потому что nPoints
не метод класса Point
.Обсуждение
Отметьте, что имена выражения могут быть квалифицированы именами типов, но не типами вообще. Последствие - то, что не возможно получить доступ к переменной класса через параметризованный тип
Вместо этого пишет каждыйclass Foo<T> { public static int classVar = 42; } Foo<String>.classVar = 91; // illegal
Это не ограничивает язык любым значимым способом. Параметры типа не могут использоваться в типах статических переменных, и таким образом, фактические параметры параметризованного типа никогда не могут влиять на тип статической переменной. Поэтому, никакое выразительное питание не теряется. Технически, имя типаFoo.classVar = 91;
Foo
выше необработанный тип, но это использование необработанных типов безопасно, и не дает начало предупреждениям
Иначе, простое имя метода обязательно появляется в контексте выражения вызова метода. В этом случае, если имя метода состоит из единственного Идентификатора, то Идентификатор является именем метода, которое будет использоваться для вызова метода. Идентификатор должен назвать по крайней мере один видимый (§6.3.1) метод, который находится в контексте в точке, где Идентификатор появляется или метод, импортированный объявлением единственного статического импорта (§7.5.3) или объявлением "статический импорт по требованию" (§7.5.4) в пределах единицы компиляции, в пределах которой появляется Идентификатор.
См. §15.12 для дальнейшего обсуждения интерпретации простых имен методов в выражениях вызова метода.
.
Идентификатор, тогда Q был уже классифицирован как имя пакета, имя типа, или имя выражения. Если Q является именем пакета, то ошибка времени компиляции происходит. Иначе, Айдахо является именем метода, которое будет использоваться для вызова метода. Если Q является именем типа, то Идентификатор должен назвать по крайней мере один static
метод типа Q. Если Q является именем выражения, то T, которым позволяют, являются типом выражения Q; Идентификатор должен назвать по крайней мере один метод типа T. См. §15.12 для дальнейшего обсуждения интерпретации квалифицированных имен методов в выражениях вызова метода.Обсуждение
Как имена выражения, имена методов могут быть квалифицированы именами типов, но не типами вообще. Импликации подобны тем для имен выражения как обсуждено в §6.5.6.2.
Отметьте, что доступность является статическим свойством, которое может быть определено во время компиляции; это зависит только от модификаторов объявления и типов. Полностью определенные имена являются средством доступа к элементам пакетов и ссылочных типов; связанные средства доступа включают выражения доступа к полю (§15.11) и выражения вызова метода (§15.12). Все три синтаксически подобны в этом".
"маркер кажется, предшествовавшим некоторой индикацией относительно пакета, введите, или выражение, имеющее тип и сопровождаемый Идентификатором, который называет элемент пакета или типа. Они все вместе известны как конструкции для квалифицированного доступа.
Управление доступом применяется к квалифицированному доступу и к вызову конструкторов по выражениям создания экземпляра класса (§15.9) и явным вызовам конструктора (§8.8.7.1). Доступность также наследование эффектов элементов класса (§8.2), включая сокрытие и метод, переопределяющий (§8.4.8.1).
public
, тогда к этому может получить доступ любой код, при условии, что единица компиляции (§7.3), в котором это объявляется, заметна. Если высокоуровневый класс или интерфейсный тип не объявляются public
, тогда к этому можно получить доступ только изнутри пакета, в котором это объявляется.
public
, тогда доступ разрешается. Все элементы интерфейсов неявно public
.
protected
, тогда доступ разрешается только, когда одно из следующего является истиной: protected
элемент или конструктор объявляются.
private
, тогда доступ разрешается, если и только если он происходит в пределах тела высокоуровневого класса (§7.6), который включает объявление элемента или конструктора.
protected
к элементу или конструктору объекта можно получить доступ снаружи пакета, в котором он объявляется только кодом, который ответственен за реализацию того объекта.protected
элемент м. объявляется. Доступ разрешается только в пределах тела подкласса S C. Кроме того, если Идентификатор обозначает поле экземпляра или метод экземпляра, то:
.
Идентификатор, где Q является ExpressionName, тогда доступ, разрешается, если и только если тип выражения Q является S или подклассом S.
.
Идентификатор, где E является Основным выражением, или по выражению E вызова метода.
Идентификатор(
. . .)
, где E является Основным выражением, тогда доступ разрешается, если и только если тип E является S или подклассом S. protected
конструктор объявляется и позволяется S быть самым внутренним классом в чей объявлении использование protected
конструктор происходит. Затем:
super(
. . .)
или квалифицированным вызовом конструктора суперкласса формы E.super(. . .)
, где E является Основным выражением, тогда доступ разрешается.
(. . .){...}
или по квалифицированному выражению создания экземпляра класса формы E.new
C(. . .){...}
, где E является Основным выражением, тогда доступ разрешается.
new
C(
. . .)
или по квалифицированному выражению создания экземпляра класса формы E.new
C(. . .)
, где E является Основным выражением, тогда доступ не разрешается. A protected
к конструктору может получить доступ выражение создания экземпляра класса (который не объявляет анонимный класс), только изнутри пакета, в котором это определяется.
и:package points; class PointVec { Point[] vec; }
которые объявляют два типов классов в пакетеpackage points; public class Point { protected int x, y; public void move(int dx, int dy) { x += dx; y += dy; } public int getX() { return x; } public int getY() { return y; } }
points
:
PointVec
не public
и не часть public
интерфейс пакета points
, а скорее может использоваться только другими классами в пакете.
Point
объявляется public
и доступно другим пакетам. Это - часть public
интерфейс пакета points
.
move
, getX
, и getY
из класса Point
объявляются public
и так доступны любому коду, который использует объект типа Point
.
x
и y
объявляются protected
и доступны вне пакета points
только в подклассах класса Point,
и только когда они - поля объектов, которые реализуются кодом, который получает доступ к ним. protected
модификатор доступа ограничивает доступ. public
модификатор, доступ к объявлению класса ограничивается пакетом, в котором это объявляется (§6.6). В примере:
два класса объявляются в единице компиляции. Классpackage points; public class Point { public int x, y; public void move(int dx, int dy) { x += dx; y += dy; }}
class PointList { Point next, prev; }
Point
доступно вне пакета points
, в то время как класс PointList
доступно для доступа только в пределах пакета. Таким образом единица компиляции в другом пакете может получить доступ points.Point
, любой при использовании его полностью определенного имени:
или при использовании объявления единственного импорта типа (§7.5.1), который упоминает полностью определенное имя, так, чтобы простое имя могло использоваться после того:package pointsUser; class Test { public static void main(String[] args) { points.Point p = new points.Point(); System.out.println(p.x + " " + p.y); } }
Однако, эта единица компиляции не может использовать или импортироватьpackage pointsUser; import points.Point; class Test { public static void main(String[] args) { Point p = new Point(); System.out.println(p.x + " " + p.y); }}
points.PointList
, который не объявляется public
и поэтому недоступный внешний пакет points
.public
, protected
, или private
определяются, элемент класса или конструктор доступны всюду по пакету, который содержит объявление класса, в котором объявляется элемент класса, но элемент класса или конструктор не доступны в любом другом пакете. Если a public
у класса есть метод или конструктор с доступом по умолчанию, тогда этот метод или конструктор не доступны для или наследованный подклассом, объявленным вне этого пакета.
Например, если мы имеем:
тогда подкласс в другом пакете может объявить несвязанноеpackage points; public class Point { public int x, y; void move(int dx, int dy) { x += dx; y += dy; } public void moveAlso(int dx, int dy) { move(dx, dy); } }
move
метод, с той же самой подписью (§8.4.2) и тип возврата. Поскольку оригинал move
метод не доступен от пакета morepoints
, super
возможно, не используется:
Поскольку перемещениеpackage morepoints; public class PlusPoint extends points.Point { public void move(int dx, int dy) { super.move(dx, dy); // compile-time error moveAlso(dx, dy); } }
Point
не переопределяется move
в PlusPoint
, метод moveAlso
в Point
никогда не призывает перемещение метода PlusPoint
.Таким образом, если Вы удаляете super.move
вызовите от PlusPoint
и выполните тестовую программу:
это обычно завершается. Если перемещениеimport points.Point; import morepoints.PlusPoint; class Test { public static void main(String[] args) { PlusPoint pp = new PlusPoint(); pp.move(1, 1);}
}
Point
были переопределены move
в PlusPoint
, тогда эта программа рекурсивно вызвала бы бесконечно, до a StackoverflowError
произошедший.public
элемент класса или конструктор доступны всюду по пакету, где это объявляется и от любого другого пакета, обеспечило пакет, в котором это объявляется, заметно (§7.4.3). Например, в единице компиляции:
package points; public class Point { int x, y; public void move(int dx, int dy) { x += dx; y += dy; moves++; } public static int moves = 0; }
public
класс Point
имеет как public
элементы move
метод и moves
поле. Они public
элементы доступны для любого другого пакета, у которого есть доступ к пакету points
. Поля x
и y
не public
и поэтому доступны только изнутри пакета points
.points
пакет объявляет:
иpackage points; public class Point { protected int x, y; void warp(threePoint.Point3d a) { if (a.z > 0) // compile-time error: cannot access a.z a.delta(this); } }
threePoint
пакет объявляет:
который определяет классpackage threePoint; import points.Point; public class Point3d extends Point { protected int z; public void delta(Point p) { p.x += this.x; // compile-time error: cannot access p.x p.y += this.y; // compile-time error: cannot access p.y } public void delta3d(Point3d q) { q.x += this.x; q.y += this.y; q.z += this.z; } }
Point3d
. Ошибка времени компиляции происходит в методе delta
здесь: это не может получить доступ к защищенным элементам x
и y
из его параметра p
, потому что, в то время как Point3d
(то класс, в который ссылки на поля x
и y
происходите), подкласс Point
(то класс, в который x
и y
объявляются), это не включается в реализацию a Point
(тип параметра p
). Метод delta3d
может получить доступ к защищенным элементам его параметра q
, потому что класс Point3d
подкласс Point
и включается в реализацию a Point3d
.Метод delta
мог попытаться бросить (§5.5, §15.16) его параметр, чтобы быть a Point3d
, но этот бросок перестал бы работать, вызывая исключение, если класс p
во время выполнения не были Point3d
.
Ошибка времени компиляции также происходит в деформации метода: это не может получить доступ к защищенному элементу z
из его параметра a
, потому что, в то время как класс Point
(то класс, в который ссылка на поле z
происходит), включается в реализацию a Point3d
(тип параметра a
), это не подкласс Point3d
(то класс, в который z
объявляется).
A
private
элемент класса или конструктор доступны только в пределах тела высокоуровневого класса (§7.6), который включает объявление элемента или конструктора. Это не наследовано подклассами. В примере:
class Point { Point() { setMasterID(); } int x, y; private int ID; private static int masterID = 0; private void setMasterID() { ID = masterID++; } }
private
элементы ID,
м.asterID
, и setMasterID
может использоваться только в пределах тела класса Point
. К ним не могут получить доступ полностью определенные имена, выражения доступа к полю, или выражения вызова метода вне тела объявления Point
.См. §8.8.8 для примера, который использует a private
конструктор.
boolean
, char
, byte
, short
, int
, long
, float
, или double
.
.
", сопровождаемый простым (элемент) имя подпакета.
.
", сопровождаемый простым именем класса или интерфейса.
[]
".
long
"long
".
java.lang
"java.lang
"потому что это - подпакет lang
из пакета java
.
Object
, который определяется в пакете java.lang
,"java.lang.Object
".
Enumeration
, который определяется в пакете java.util
,"java.util.Enumeration
".
double
double[]
".
String
java.lang.String[][][][]
".
полностью определенное имя типаpackage points; class Point { int x, y; } class PointVec { Point[] vec; }
Point
"points.Point
"; полностью определенное имя типа PointVec
"points.PointVec
"; и полностью определенное имя типа поля vec
из класса PointVec
"points.Point[]
".
У каждого пакета, высокоуровневого класса, высокоуровневого интерфейса, и типа примитива есть каноническое имя. У типа массива есть каноническое имя, если и только если у его типа элемента есть каноническое имя. Задействованный класс или элемент взаимодействуют через интерфейс, у М. объявленного в другом классе C есть каноническое имя, если и только если у C есть каноническое имя. В этом случае каноническое имя М. состоит из канонического имени C, сопровождаемого ". ", сопровождаемый простым именем М. Для каждого пакета, высокоуровневого класса, высокоуровневого интерфейса и типа примитива, каноническое имя является тем же самым как полностью определенным именем. Каноническое имя типа массива определяется только, когда у компонентного типа массива есть каноническое имя. В этом случае каноническое имя типа массива состоит из канонического имени компонентного типа типа массива, сопровождаемого"[]
".
Различие между полностью определенным именем и каноническим именем может быть замечено в примерах, таких как:
В этом примере обаpackage p; class O1 { class I{}} class O2 extends O1{};
p.O1.I
и p.O2.I
полностью определяются имена, которые обозначают тот же самый класс, но только p.O1.I
его каноническое имя.Мы рекомендуем эти соглашения для использования во всех программах, записанных в языке программирования Java. Однако, эти соглашения не должны сопровождаться по-рабски если долго сохранено стандартное использование, диктует иначе. Так, например, sin
и cos
методы класса java.lang.Math
имейте математически стандартные имена, даже при том, что эти имена методов презирают соглашение, предложенное здесь, потому что они коротки и не являются глаголами.
com
, edu
, gov
, mil
, net
, org
, или двухбуквенный код страны ISO такой как uk
или jp
. Вот примеры гипотетических уникальных имен, которые могли бы быть сформированы в соответствии с этим соглашением:
com.JavaSoft.jag.Oak org.npr.pledge.driver uk.ac.city.rugby.game
У имен пакетов, предназначенных только для локального использования, должен быть первый идентификатор, который начинается со строчной буквы, но что первый идентификатор определенно не должен быть идентификатором java
; имена пакета, которые запускаются с идентификатора java
резервируются Sun для того, чтобы назвать пакеты платформы Java.
Когда имена пакета происходят в выражениях:
import
объявления (§7.5) могут обычно использоваться, чтобы сделать доступным имена типов объявленный в том пакете.
Первый компонент имени пакета обычно легко не принимается за имя типа, поскольку имя типа обычно начинается с единственной прописной буквы. (Язык программирования Java фактически не полагается на различия случая, чтобы определить, является ли имя именем пакета или именем типа.)
ClassLoader
SecurityManager
Thread
Dictionary
BufferedInputStream
Аналогично, имена интерфейсных типов должны быть короткими и дескриптивными, не чрезмерно долго, в смешанном случае с первой буквой каждого использованного для своей выгоды слова. Имя может быть дескриптивным существительным или именной группой, которая является соответствующей, когда интерфейс используется, как будто это был абстрактный суперкласс, такой как интерфейсы java.io.DataInput
и java.io.DataOutput
; или это может быть прилагательное, описывающее поведение, что касается интерфейсов Runnable
и Cloneable
.
Затемнение включения класса и интерфейсных имен типов редко. Имена полей, параметров, и локальных переменных обычно не затеняют имена типов, потому что они традиционно начинают со строчной буквы, тогда как имена типов традиционно начинаются с прописной буквы.
Обсуждение
Это облегчает отличать формальные параметры типа от обычных классов и интерфейсов.
Контейнерные типы должны использовать имя E
для их типа элемента. Карты должны использовать K
для типа их ключей и V
для типа их значений. Имя X
должен использоваться для произвольных типов исключения. Мы используем T
для типа, всякий раз, когда нет ничего более определенного о типе, чтобы отличить это.
Обсуждение
Это часто имеет место в универсальных методах.
Если есть многократные параметры типа, которые обозначают произвольные типы, нужно использовать буквы тот сосед T
в алфавите, такой как S
. Поочередно, приемлемо использовать числовые нижние индексы (например, T1, T2
) различать среди различных переменных типа. В таких случаях должны быть преобразованы в нижний индекс все переменные с тем же самым префиксом.
Обсуждение
Если универсальный метод появляется в универсальном классе, это - хорошая идея избегать использования тех же самых имен для параметров типа метода и класса, избежать беспорядка. То же самое применяется к вложенным универсальным классам.
Обсуждение
Эти соглашения иллюстрируются во фрагментах кода ниже:
public class HashSet<E> extends AbstractSet<E> { ... } public class HashMap<K,V> extends AbstractMap<K,V> { ... } public class ThreadLocal<T> { ... } public interface Functor<T, X extends Throwable> { T eval() throws X; }
E, K, T, V, X
) не должен использоваться для параметров типа, которые не попадают в определяемые категории.
get
и set
атрибут, который мог бы считаться переменной V, нужно назвать get
V и set
V. Примером являются методы getPriority
и setPriority
из класса Thread
.
length
, как в классе String
.
boolean
условие V об объекте нужно назвать is
V. Примером является метод isInterrupted
из класса Thread
.
to
F. Примерами является метод toString
из класса Object
и методы toLocaleString
и toGMTString
из класса java.util.Date
. Имена методов не могут затенить или быть затенены другими именами (§6.5.7).
final
должен быть в смешанном случае с нижним регистром, сначала обозначают буквами и первые буквы последующих использованных для своей выгоды слов. Отметьте, что у хорошо разработанных классов есть очень немногие public
или protected
поля, за исключением полей, которые являются константами (final
static
поля) (§6.8.6).У полей должны быть имена, которые являются существительными, именными группами, или сокращениями для существительных. Примерами этого соглашения являются поля buf
, pos
, и count
из класса java.io.ByteArrayInputStream
и поле bytesTransferred
из класса java.io.InterruptedIOException
.
Затемнение включения имен полей редко.
import
объявление (§7.5) может обычно использоваться, чтобы сделать доступным имена типов объявленный в том пакете.
final
переменные типов классов могут традиционно быть, последовательность одного или более слов, акронимов, или сокращений, всего верхнего регистра, с компонентами, разделенными подчеркиванием"_
"символы. Постоянные имена должны быть дескриптивными и весьма обязательно сокращенными. Традиционно они могут быть любой соответствующей частью речи. Примеры имен для констант включают MIN_VALUE
, MAX_VALUE
, MIN_RADIX
, и MAX_RADIX
из класса Character
.Группа констант, которые представляют альтернативные значения набора, или, менее часто, маскируя биты в целочисленном значении, иногда полезно определяется с общим акронимом как префикс имени, как в:
Затемнение включения постоянных имен редко:interface ProcessStates { int PS_RUNNING = 0; int PS_SUSPENDED = 1; }
cp
для переменной, содержащей ссылку на a ColoredPoint
buf
содержание указателя на a buffer
из некоторого вида
Односимвольной локальной переменной или названий параметра нужно избежать, за исключением временного и переменных цикличного выполнения, или где переменная содержит непримечательное значение типа. Стандартные односимвольные имена:
b
для a byte
c
для a char
d
для a double
e
для Exception
f
для a float
i
, j
, и k
для целых чисел
l
для a long
o
для Object
s
для a String
v
для произвольного значения некоторого типа Локальная переменная или названия параметра, которые состоят только из двух или трех строчных букв, не должны конфликтовать с начальными кодами страны и доменными именами, которые являются первым компонентом уникальных имен пакета (§7.7).
Содержание | Предыдущий | Следующий | Индекс | Спецификация языка Java Третий Выпуск |
Авторское право © 1996-2005 Sun Microsystems, Inc. Все права защищены
Пожалуйста, отправьте любые комментарии или исправления через нашу