Spec-Zone .ru
спецификации, руководства, описания, API
Содержание | Предыдущий | Следующий | Индекс Спецификация языка Java
Второй Выпуск


ГЛАВА 6

Имена


Имена используются, чтобы обратиться к объектам, объявленным в программе. Объявленный объект (§6.1) является пакетом, типом класса, интерфейсным типом, элемент (класс, интерфейс, поле, или метод) ссылочного типа, параметр (к методу, конструктору, или обработчику исключений), или локальная переменная.

Имена в программах или просты, состоя из единственного идентификатора, или квалифицированный, состоя из последовательности идентификаторов, разделенных"."маркеры (§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.1). Имя метода может появиться в выражении только как часть выражения вызова метода (§15.12). Имя класса или интерфейсного типа может появиться в выражении только как часть литерала класса (§15.8.2), квалифицированный это выражение (§15.8.4), выражение создания экземпляра класса (§15.9), выражение создания массива (§15.10), выражение броска (§15.16), или instanceof выражение (§15.20.2), или как часть полностью определенного имени для поля или метода. Имя пакета может появиться в выражении только как часть полностью определенного имени для класса или соединить интерфейсом с типом.

6.1 Объявления

Объявление вводит объект в программу и включает идентификатор (§3.8), который может использоваться на имя, чтобы обратиться к этому объекту. Объявленный объект является одним из следующего:

Конструкторы (§8.8) также представляются объявлениями, но используют имя класса, в котором они объявляются вместо того, чтобы представить новое имя.

6.2 Имена и Идентификаторы

Имя используется, чтобы обратиться к объекту, объявленному в программе.

Есть две формы имен: простые имена и полностью определенные имена. Простое имя является единственным идентификатором. Полностью определенное имя состоит из имени,"."маркер, и идентификатор.

В определении значения имени (§6.5), принимается во внимание контекст, в котором появляется имя. Правила §6.5 различают среди контекстов, где имя должно обозначить (обратитесь к), пакет (§6.5.3), тип (§6.5.5), переменная или значение в выражении (§6.5.6), или метод (§6.5.7).

Не все идентификаторы в программах являются частью имени. Идентификаторы также используются в следующих ситуациях:

В примере:

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 в пределах помеченного оператора.

6.3 Контекст Объявления

Контекст объявления является областью программы, в пределах которой объект, объявленный объявлением, может быть отнесен в использование простого имени (если это видимо (§6.3.1)). Объявление, как говорят, находится в контексте в определенной точке в программе, если и только если контекст объявления включает ту точку.

Правила обзора данных для различных конструкций даются в разделах, которые описывают те конструкции. Для удобства правила повторяются здесь:

Контекст объявления заметного (§7.4.3) высокоуровневого пакета является всеми заметными единицами компиляции (§7.3). Объявление пакета, который не заметен, никогда не находится в контексте. Объявления подпакета никогда не находятся в контексте.

Контекст типа, импортированного объявлением единственного импорта типа (§7.5.1) или объявлением "импорт типа по требованию" (§7.5.2), является всем классом и интерфейсными описаниями типа (§7.6) в единице компиляции, в которой появляется объявление импорта.

Контекст высокоуровневого типа является всеми описаниями типа в пакете, в котором объявляется высокоуровневый тип.

Контекст метки, объявленной помеченным оператором, является оператором, сразу включенным помеченным оператором.

Контекст объявления элемента м. объявил в или наследовался типом класса C, все тело C, включая любые объявления вложенного типа.

Контекст объявления элемента м. объявил в или наследовался интерфейсным типом, я - все тело меня, включая любые объявления вложенного типа.

Контекст параметра метода (§8.4.1) или конструктор (§8.8.1) является всем телом метода или конструктора.

Контекст объявления локальной переменной в блоке (§14.4.2) является остальной частью блока, в котором объявление появляется, запускаясь с его собственного инициализатора (§14.4) и включая дальнейшие операторы объявления направо в операторе объявления локальной переменной.

Контекст локального класса, объявленного в блоке, является остальной частью сразу блока включения, включая его собственное объявление класса.

Контекст локальной переменной объявляется в части ForInit a for оператор (§14.13) включает все следующее:

Контекст параметра обработчика исключений, который объявляется в a catch пункт a try оператор (§14.19) является всем блоком, связанным с catch.

Эти правила подразумевают, что объявления класса и интерфейсных типов не должны появиться перед использованием типов.

В примере:

package points;
class Point {
	int x, y;
	PointList list;
	Point next;
}
class PointList {
	Point first;
}
использование PointList в классе Point корректно, потому что контекст объявления класса PointList включает оба класса Point и класс PointList, так же как любые другие описания типа в других единицах компиляции пакета points.

6.3.1 Объявления затенения

Некоторые объявления могут быть затенены в части их контекста другим объявлением того же самого имени, когда простое имя не может использоваться, чтобы обратиться к объявленному объекту.

Объявление d типа, названного n тенями объявления любых других типов, названных n, которые находятся в контексте в точке, где d происходит всюду по контексту d.

Объявление d поля, локальной переменной, параметра метода, параметра конструктора или параметра обработчика исключений, названного n тенями объявления любых других полей, локальных переменных, параметров метода, параметров конструктора или параметров обработчика исключений, названных n, которые находятся в контексте в точке, где d происходит всюду по контексту d.

Объявление d метки, названной n тенями объявления любых других меток, названных n, которые находятся в контексте в точке, где d происходит всюду по контексту d.

Объявление d метода, названного n тенями объявления любых других методов, названных n, которые находятся в контексте включения в точке, где d происходит всюду по контексту d.

Объявление пакета никогда тени любое другое объявление.

Объявление d единственного импорта типа в единице компиляции c пакета p, который импортирует тип, названный n тенями объявления:

всюду по c.

Объявление "импорт типа по требованию" никогда не заставляет никакое другое объявление быть затененным.

Объявление d, как говорят, видимо в точке p в программе, если контекст d включает p, и d не затенен любым другим объявлением в p. Когда момент программы, который мы обсуждаем, будет четким от контекста, мы будем часто просто говорить, что объявление видимо.

Отметьте, что затенение отлично от сокрытия (§8.3, §8.4.6.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
Этот пример объявляет:

Так как контекст переменной класса включает все тело класса (§8.2) переменная класса x обычно было бы доступно всюду по всему телу метода main. В этом примере, однако, переменной класса x затенено в пределах тела метода main объявлением локальной переменной x.

Локальная переменная имеет как ее остальная часть контекста блока, в котором она объявляется (§14.4.2); в этом случае это - остальная часть тела main метод, а именно, его инициализатор"0"и вызовы print и println.

Это означает что:

Следующий пример иллюстрирует затенение одного описания типа другим:
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 объявленный здесь в предпочтении к классу java.util.Vector это могло бы быть импортировано по требованию.

6.3.2 Затененные Объявления

Простое имя может произойти в контекстах, где оно может потенциально быть интерпретировано как имя переменной, типа или пакета. В этих ситуациях правила §6.5 определяют, что переменная будет выбрана в предпочтении к типу, и что тип будет выбран в предпочтении к пакету. Таким образом это, может иногда быть невозможно обратиться к видимому типу или объявлению пакета через его простое имя. Мы говорим, что такое объявление затеняется.

Затемнение отлично от затенения (§6.3.1) и скрывающийся (§8.3, §8.4.6.2, §8.5, §9.3, §9.5). Соглашения о присвоении имен §6.8 помогают уменьшить затемнение.

6.4 Элементы и Наследование

У пакетов и ссылочных типов есть элементы.

Этот раздел обеспечивает краткий обзор элементов пакетов и ссылочных типов здесь как фон для обсуждения полностью определенных имен и определения значения имен. Для полного описания членства см. §7.1, §8.2, §9.2, и §10.7.

6.4.1 Элементы Пакета

Элементы пакета (§7) определяются в §7.1. Для удобства мы повторяем что спецификация здесь:

Элементы пакета являются подпакетами и всем верхним уровнем (§7.6) класс (§8) и высокоуровневый интерфейс (§9) типы, объявленные во всех единицах компиляции (§7.3) пакета.

Вообще, подпакеты пакета определяются хост-системой (§7.2). Однако, пакет java всегда включает подпакеты lang и io и может включать другие подпакеты. Ни у каких двух отличных элементов того же самого пакета не может быть того же самого простого имени (§7.1), но у элементов различных пакетов может быть то же самое простое имя.

Например, возможно объявить пакет:

package vector;
public class Vector { Object[] vec; }
это имеет как элемент a public класс называют Vector, даже при том, что пакет java.util также объявляет названный класс Vector. Эти два типов классов отличаются, отражаются фактом, что у них есть различные полностью определенные имена (§6.7). Полностью определенное имя этого примера Vector vector.Vector, тогда как java.util.Vector полностью определенное имя стандарта Vector класс. Поскольку пакет vector содержит названный класс Vector, этому нельзя было также назвать подпакет Vector.

6.4.2 Элементы Типа класса

Элементы типа класса (§8.2) являются классами (§8.5, §9.5), интерфейсы (§8.5, §9.5), поля (§8.3, §9.3, §10.7), и методы (§8.4, §9.4). Элементы или объявлены в типе, или наследованы, потому что они - доступные элементы суперкласса или суперинтерфейса, которые не являются ни частными, ни не скрываются, ни переопределенные (§8.4.6).

Элементы типа класса являются всем следующим:

Конструкторы (§8.8) не являются элементами.

Нет никакого ограничения против поля и метода типа класса, имеющего то же самое простое имя. Аналогично, нет никакого ограничения против задействованного класса или задействованного интерфейса типа класса, имеющего то же самое простое имя как поле или метод того типа класса.

У класса может быть два или больше поля с тем же самым простым именем, если они объявлены в различных интерфейсах и наследованы. Попытка обратиться к любому из полей ее простым именем приводит к ошибке времени компиляции (§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.

6.4.3 Элементы Интерфейсного Типа

Элементы интерфейсного типа (§9.2) могут быть классами (§8.5, §9.5), интерфейсы (§8.5, §9.5), поля (§8.3, §9.3, §10.7), и методы (§8.4, §9.4).The элементы интерфейса:

У интерфейса может быть два или больше поля с тем же самым простым именем, если они объявлены в различных интерфейсах и наследованы. Попытка обратиться к любому такому полю его простым именем приводит к ошибке времени компиляции (§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.

6.4.4 Элементы Типа Массива

Элементы типа массива определяются в §10.7. Для удобства мы повторяем ту спецификацию здесь.

Элементы типа массива являются всем следующим:

Пример:

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[].

6.5 Определение Значения Имени

Значение имени зависит от контекста, в котором оно используется. Определение значения имени требует трех шагов. Во-первых, контекст заставляет имя синтаксически попадать в одну из шести категорий: PackageName, TypeName, ExpressionName, MethodName, PackageOrTypeName, или AmbiguousName. Во-вторых, имя, которое первоначально классифицируется его контекстом как AmbiguousName или как Пакет-OrTypeName, тогда повторно классифицируется, чтобы быть PackageName, TypeName, или ExpressionName. В-третьих, получающаяся категория тогда диктует заключительное определение значения имени (или ошибка компиляции, если у имени нет никакого значения).

Использование контекста помогает минимизировать конфликты имен между объектами различных видов. Такие конфликты будут редки, если соглашения о присвоении имен, описанные в §6.8, будут сопровождаться. Однако, конфликты могут возникнуть неумышленно как типы, разработанные различными программистами, или различные организации развиваются. Например, у типов, методов, и полей может быть то же самое имя. Всегда возможно различить метод и поле с тем же самым именем, так как контекст использования всегда говорит, предназначается ли метод.

6.5.1 Синтаксическая Классификация Имени Согласно Контексту

Имя синтаксически классифицируется как PackageName в этих контекстах:

Имя синтаксически классифицируется как TypeName в этих контекстах:

Имя синтаксически классифицируется как ExpressionName в этих контекстах:

Имя синтаксически классифицируется как MethodName в этом контексте:

Имя синтаксически классифицируется как PackageOrTypeName в этих контекстах:

Имя синтаксически классифицируется как AmbiguousName в этих контекстах:

6.5.2 Переклассификация Контекстуально Неоднозначных Имен

AmbiguousName тогда повторно классифицируется следующим образом:

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. Поэтому, каждое из имен:

org.rpgpoet.Music.wizards
org.rpgpoet.Music
org.rpgpoet
org 
первоначально классифицируется как AmbiguousName. Они тогда повторно классифицируются:

6.5.3 Значение Имен Пакета

Значение имени, классифицированного как PackageName, определяется следующим образом.

6.5.3.1 Простые Имена Пакета

Если имя пакета состоит из единственного Идентификатора, то этот идентификатор обозначает высокоуровневый пакет, названный тем идентификатором. Если никакой высокоуровневый пакет того имени не находится в контексте (§7.4.4), то ошибка времени компиляции происходит.

6.5.3.2 Квалифицированные Имена Пакета

Если имя пакета имеет форму Q.Идентификатор, тогда Q должен также быть именем пакета. Имя Q пакета.Идентификатор называет пакет, который является элементом под названием Идентификатор в пределах пакета, названного Q. Если Q не называет заметный пакет (§7.4.3), или Идентификатор не является простым именем заметный подпакет того пакета, то ошибка времени компиляции происходит.

6.5.4 Значение PackageOrTypeNames

6.5.4.1 Простой PackageOrTypeNames

Если PackageOrTypeName, Q, происходит в пределах типа по имени Q, то PackageOrTypeName повторно классифицируется как TypeName.

Иначе, PackageOrTypeName повторно классифицируется как PackageName. Значение PackageOrTypeName является значением повторно классифицированного имени.

6.5.4.2 Квалифицированный PackageOrTypeNames

Учитывая квалифицированный PackageOrTypeName формы Q.Id, если у типа или пакета, обозначенного Q, есть тип элемента под названием Идентификатор, то квалифицированное имя PackageOrTypeName повторно классифицируется как TypeName.

Иначе, это повторно классифицируется как PackageName. Значение квалифицированного PackageOrTypeName является значением повторно классифицированного имени.

6.5.5 Значение Имен типов

Значение имени, классифицированного как TypeName, определяется следующим образом.

6.5.5.1 Простые Имена типов

Если имя типа состоит из единственного Идентификатора, то идентификатор должен произойти в пределах объявления типа с этим именем, или ошибка времени компиляции происходит.

Возможно, что идентификатор происходит в рамках больше чем одного типа с тем именем, когда тип, обозначенный именем, определяется следующим образом:

Этот порядок на рассмотрение описаний типа разрабатывается, чтобы выбрать самое явное из двух или больше применимых описаний типа.

6.5.5.2 Квалифицированные Имена типов

Если имя типа имеет форму Q.Идентификатор, тогда 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 доступно в этом пакете.

6.5.6 Значение Имен Выражения

Значение имени, классифицированного как ExpressionName, определяется следующим образом.

6.5.6.1 Простые Имена Выражения

Если имя выражения состоит из единственного Идентификатора, то:

В примере:

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

6.5.6.2 Квалифицированные Имена Выражения

Если имя выражения имеет форму Q.Идентификатор, тогда Q был уже классифицирован как имя пакета, имя типа, или имя выражения:

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.

6.5.7 Значение Имен методов

MethodName может появиться только в выражении вызова метода (§15.12). Значение имени, классифицированного как MethodName, определяется следующим образом.

6.5.7.1 Простые Имена методов

Если имя метода состоит из единственного Идентификатора, то Идентификатор является именем метода, которое будет использоваться для вызова метода. Идентификатор должен назвать по крайней мере один метод класса или интерфейса, в пределах объявления которого появляется Идентификатор. См. §15.12 для дальнейшего обсуждения интерпретации простых имен методов в выражениях вызова метода.

6.5.7.2 Квалифицированные Имена методов

Если имя метода имеет форму Q.Идентификатор, тогда Q был уже классифицирован как имя пакета, имя типа, или имя выражения. Если Q является именем пакета, то ошибка времени компиляции происходит. Иначе, Айдахо является именем метода, которое будет использоваться для вызова метода. Если Q является именем типа, то Идентификатор должен назвать по крайней мере один static метод типа Q. Если Q является именем выражения, то T, которым позволяют, являются типом выражения Q; Идентификатор должен назвать по крайней мере один метод типа T. См. §15.12 для дальнейшего обсуждения интерпретации квалифицированных имен методов в выражениях вызова метода.

6.6 Управление доступом

Язык программирования Java обеспечивает механизмы для управления доступом, чтобы предотвратить пользователей пакета или класса от в зависимости от ненужных деталей реализации того пакета или класса. Если доступ разрешается, то объект, к которому получают доступ, как говорят, доступен.

Отметьте, что доступность является статическим свойством, которое может быть определено во время компиляции; это зависит только от модификаторов объявления и типов. Полностью определенные имена являются средством доступа к элементам пакетов и ссылочных типов; связанные средства доступа включают выражения доступа к полю (§15.11) и выражения вызова метода (§15.12). Все три синтаксически подобны в этом"."маркер кажется, предшествовавшим некоторой индикацией относительно пакета, введите, или выражение, имеющее тип и сопровождаемый Идентификатором, который называет элемент пакета или типа. Они все вместе известны как конструкции для квалифицированного доступа.

Управление доступом применяется к квалифицированному доступу и к вызову конструкторов по выражениям создания экземпляра класса (§15.9) и явным вызовам конструктора (§8.8.5). Доступность также влияет на наследование элементов класса (§8.2), включая сокрытие и метод, переопределяющий (§8.4.6.1).

6.6.1 Определение Доступности

6.6.2 Детали о protected Access

A protected к элементу или конструктору объекта можно получить доступ снаружи пакета, в котором он объявляется только кодом, который ответственен за реализацию того объекта.

6.6.2.1 Доступ к a protected Элемент

Позвольте C быть классом в который a protected элемент м. объявляется. Доступ разрешается только в пределах тела подкласса S C. Кроме того, если Идентификатор обозначает поле экземпляра или метод экземпляра, то:

6.6.2.2 Квалифицированный Доступ к a protected Конструктор

Позвольте C быть классом в который a protected конструктор объявляется и позволяется S быть самым внутренним классом в чей объявлении использование protected конструктор происходит. Затем:

6.6.3 Пример Управления доступом

Для примеров управления доступом рассмотрите эти две единицы компиляции:

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:

См. §6.6.7 для примера как protected модификатор доступа ограничивает доступ.

6.6.4 Пример: Доступ к public и Non-public Классы

Если классу недостает 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, любой при использовании его полностью определенного имени:

package pointsUser;
class Test {
	public static void main(String[] args) {
		points.Point p = new points.Point();
		System.out.println(p.x + " " + p.y);
	}
}
или при использовании объявления единственного импорта типа (§7.5.1), который упоминает полностью определенное имя, так, чтобы простое имя могло использоваться после того:

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.

6.6.5 Пример: Поля доступа по умолчанию, Методы, и Конструкторы

Если ни один из модификаторов доступа 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.3.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 произошедший.

6.6.6 Пример: public Поля, Методы, и Конструкторы

A 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.

6.6.7 Пример: protected Поля, Методы, и Конструкторы

Рассмотрите этот пример, где 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 объявляется).

6.6.8 Пример: private Поля, Методы, и Конструкторы

A private элемент класса или конструктор доступны только в пределах тела класса, в котором элемент объявляется и не наследован подклассами. В примере:

class Point {
	Point() { setMasterID(); }
	int x, y;
	private int ID;
	private static int masterID = 0;
	private void setMasterID() { ID = masterID++; }
}
private элементы ID, masterID, и setMasterID может использоваться только в пределах тела класса Point. К ним не могут получить доступ полностью определенные имена, выражения доступа к полю, или выражения вызова метода вне тела объявления Point.

См. §8.8.8 для примера, который использует a private конструктор.

6.7 Полностью определенные Имена и Канонические имена

У каждого пакета, высокоуровневого класса, высокоуровневого интерфейса, и типа примитива есть полностью определенное имя. У типа массива есть полностью определенное имя, если и только если у его типа элемента есть полностью определенное имя.

Примеры:

В примере:

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 его каноническое имя.

6.8 Соглашения о присвоении имен

Библиотеки классов платформы Java пытаются использовать, когда бы ни было возможно, имена, выбранные согласно соглашениям, представленным здесь. Эти соглашения помогают сделать код более читаемым и избежать определенных видов конфликтов имен.

Мы рекомендуем эти соглашения для использования во всех программах, записанных в языке программирования Java. Однако, эти соглашения не должны сопровождаться по-рабски если долго сохранено стандартное использование, диктует иначе. Так, например, sin и cos методы класса java.lang.Math имейте математически стандартные имена, даже при том, что эти имена методов презирают соглашение, предложенное здесь, потому что они коротки и не являются глаголами.

6.8.1 Имена пакета

Имена пакетов, которые должны быть сделаны широко доступными, должны быть сформированы как описано в §7.7. Такие имена всегда являются полностью определенными именами, первый идентификатор которых состоит из двух или трех строчных букв, которые называют Интернет-домен, такой как 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.

Когда имена пакета происходят в выражениях:

6.8.2 Класс и Интерфейсные Имена типов

Имена типов классов должны быть дескриптивными существительными или именными группами, не чрезмерно долго, в смешанном случае с первой буквой каждого использованного для своей выгоды слова. Например:

ClassLoader
SecurityManager
Thread
Dictionary
BufferedInputStream
Аналогично, имена интерфейсных типов должны быть короткими и дескриптивными, не чрезмерно долго, в смешанном случае с первой буквой каждого использованного для своей выгоды слова. Имя может быть дескриптивным существительным или именной группой, которая является соответствующей, когда интерфейс используется, как будто это был абстрактный суперкласс, такой как интерфейсы java.io.DataInput и java.io.DataOutput; или это может быть прилагательное, описывающее поведение, что касается интерфейсов Runnable и Cloneable.

Затемнение включения класса и интерфейсных имен типов редко. Имена полей, параметров, и локальных переменных обычно не затеняют имена типов, потому что они традиционно начинают со строчной буквы, тогда как имена типов традиционно начинаются с прописной буквы.

6.8.3 Имена методов

Имена методов должны быть глаголами или фразами глагола, в смешанном случае, с первым нижним регистром буквы и первой буквой любых последующих использованных для своей выгоды слов. Вот некоторые дополнительные определенные соглашения для имен методов:

Когда бы ни было возможно и соответствующий, базируя имена методов в новом классе на именах в существующем классе, который подобен, особенно класс от классов Прикладного программного интерфейса Java, облегчит использовать.

Имена методов не могут затенить или быть затенены другими именами (§6.5.7).

6.8.4 Имена полей

Имена полей, которые не являются final должен быть в смешанном случае с нижним регистром, сначала обозначают буквами и первые буквы последующих использованных для своей выгоды слов. Отметьте, что у хорошо разработанных классов есть очень немногие public или protected поля, за исключением полей, которые являются константами (final static поля) (§6.8.5).

У полей должны быть имена, которые являются существительными, именными группами, или сокращениями для существительных. Примерами этого соглашения являются поля buf, pos, и count из класса java.io.ByteArrayInputStream и поле bytesTransferred из класса java.io.InterruptedIOException.

Затемнение включения имен полей редко.

6.8.5 Постоянные Имена

Имена констант в интерфейсных типах должны быть, и final переменные типов классов могут традиционно быть, последовательность одного или более слов, акронимов, или сокращений, всего верхнего регистра, с компонентами, разделенными подчеркиванием"_"символы. Постоянные имена должны быть дескриптивными и весьма обязательно сокращенными. Традиционно они могут быть любой соответствующей частью речи. Примеры имен для констант включают MIN_VALUE, MAX_VALUE, MIN_RADIX, и MAX_RADIX из класса Character.

Группа констант, которые представляют альтернативные значения набора, или, менее часто, маскируя биты в целочисленном значении, иногда полезно определяется с общим акронимом как префикс имени, как в:

interface ProcessStates {
	int PS_RUNNING = 0;
	int PS_SUSPENDED = 1;
}
Затемнение включения постоянных имен редко:

6.8.6 Локальная переменная и Названия параметра

Локальная переменная и названия параметра должны быть короткими, все же значимыми. Они часто - короткие последовательности строчных букв, которые не являются словами. Например:

Односимвольной локальной переменной или названий параметра нужно избежать, за исключением временного и переменных цикличного выполнения, или где переменная содержит непримечательное значение типа. Стандартные односимвольные имена:

Локальная переменная или названия параметра, которые состоят только из двух или трех строчных букв, не должны конфликтовать с начальными кодами страны и доменными именами, которые являются первым компонентом уникальных имен пакета (§7.7).


Содержание | Предыдущий | Следующий | Индекс Спецификация языка Java
Второй Выпуск
Авторское право © Sun Microsystems, Inc 2000 года. Все права защищены
Пожалуйста, отправьте любые комментарии или исправления к jls@java.sun.com