Перейти на главную   
  helloworld.ru - документация и книги по программированию  
helloworld.ru - документация и книги по программированию
    главная     хостинг    
Поиск по сайту:  
Смотрите также
Языки программирования
C#
MS Visual C++
Borland C++
C++ Builder
Visual Basic
Quick Basic
Turbo Pascal
Delphi
JavaScript
Java
PHP
Perl
Assembler
AutoLisp
Fortran
Python
1C

Интернет-технологии
HTML
VRML
HTTP
CGI
FTP
Proxy
DNS
протоколы TCP/IP
Apache

Web-дизайн
HTML
Дизайн
VRML
PhotoShop
Cookie
CGI
SSI
CSS
ASP
PHP
Perl

Программирование игр
DirectDraw
DirectSound
Direct3D
OpenGL
3D-графика
Графика под DOS

Алгоритмы
Численные методы
Обработка данных

Сис. программирование
Драйверы

Базы данных
MySQL
SQL

Другое

Хостинг


Друзья
demaker.ru
Реклама

Лучший хостинг. Аренда серверов




helloworld.ru

ГЛАВА 6. Имена

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

Имена в программах на языке Ява бывают простые, состоящие из единственного идентификатора, или квалифицированные, состоящие из последовательности идентификаторов отделенных знаками "." (§6.2).

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

Пакеты и ссылочные типы (классовые типы, интерфейсные типы и тип массив) содержат члены (§6.4). На член можно сослаться, используя квалифицированное имя N.x, где N представляет собой простое, либо квалифицированное имя, а x идентификатор. Если N имя пакета, тогда x является членом этого пакета – классовым типом, либо интерфейсным типом, либо подпакетом. Если N имя ссылочного типа или переменная этого типа, тогда x - имя члена данного типа – поля или метода.

При определении значения имени (§6.5), Ява использует окружающий контекст для распознавания пакетов, типов, переменных и методов с одним и тем же именем.

В объявлении класса, интерфейса, метода, или поля может быть задано управление доступом (§6.6) , определяющее когда разрешен доступ к члену. Доступ – понятие отличное от области действия; доступ определяет часть текста программы на языке Ява, внутри которой к объявленному объекту можно обратиться по квалифицированному имени, с помощью выражения доступа к полю (§15.10) или с помощью выражения вызова метода (§15.11) , в котором метод не задан простым именем. Доступ по умолчанию означает, что элемент доступен везде внутри пакета, который содержит его описание; кроме того возможен доступ, задаваемый модификаторами public (доступный), protected (защищенный) и private (скрытый).

Полностью квалифицированные имена (§6.7) и соглашения по именованию (§6.8) , также рассмотрены в этой главе.

Имя поля, параметра, или локальной переменной могут использоваться в качестве выражения (§15.13.1). Имя метода может появиться в выражении только как часть выражения вызова метода (§15.11) . Имя классового типа или интерфейсного типа может появиться в выражении только как часть выражения создания экземпляра класса (§15.8) , выражения создания массива (§15.9) , выражения приведения (§15.15) , или в выражении instanceof (§15.19.2) , или как часть квалифицированного имени поля или метода. Имя пакета может появиться в выражении только как часть квалифицированного имени для классового или интерфейсного типов.

6.1 Объявления

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

  • Пакет, указанный в объявлении пакета package (§7.4)
  • Импортированный тип, объявленный в описании одиночного импорта типа (§7.5.1) , или в описании импорта типа по шаблону (§7.5.2)
  • Класс, объявленный в описании классового типа (§8.1)
  • Интерфейс, объявленный в описании интерфейсного типа (§9.1)
  • Член ссылочного типа (§8.2, §9.2, §10.7) , один из следующего:
  • поле, одно из следующего:

  • поле объявленное в классовом типе (§8.3)
  • константное поле объявленное в интерфейсном типе (§9.3)
  • поле length, которое, неявно является членом каждого типа массив (§10.7)
  • метод, один из следующих:
  • метод (абстрактный или иной) объявленный в классовом типе (§8.4)
  • метод (всегда абстрактный) объявленный в интерфейсном типе (§9.4)
  • Параметр, один из следующего:
  • параметр метода или конструктора класса (§8.4.1, §8.6.1)
  • параметр абстрактного метода интерфейса (§9.4)
  • параметр обработчика исключительных ситуаций, объявленный в операторе catch оператора try.
  • Локальная переменная, одна из следующих:
  • локальная переменная, объявленная в блоке (§14.3)
  • локальная переменная, объявленная в операторе for (§14.12)

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

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

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

Имеются две формы имен: простое имя и квалифицированное имя. Простое имя представляет собой единственный идентификатор. Квалифицированное имя состоит из имени, знака ".", и идентификатора.

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

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

  • В описаниях (§6.1) , где идентификатор может задавать имя, под которым будет известен объявленный объект
  • В области выражений доступа (§15.10) , куда идентификатор входит после знака "." указывая член объекта, который представляет собой значение выражения или ключевое слово super, которое появляется перед знаком ".".
  • В некоторых выражениях вызова метода (§15.11) , где идентификатор может появиться после знака "." и перед знаком "("для указания метода вызываемого для объекта, который представляет собой значение выражения или ключевое слово super, которое появляется перед знаком ".".
  • В качестве метки в помеченных операторах (§14.6) и в операторах break (§14.13) и continue (§14.14) , которые ссылаются на метки операторов.

В примере:


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.11) . Второе появление length не имя, а идентификатор появляющийся в выражении вызова метода (§15.11).

Идентификаторы, использованные в помеченных операторах и их объединенных 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 (§20.12.26) , где метка первоначально называлась test. Изменение метки так, что она получает такое же имя, как и локальная переменная i, не скрывает метку в области действия описания i. Идентификатор max может также использоваться в качестве метки оператора; метка не будет скрывать локальную переменную max внутри помеченного оператора.

6.3 Область действия простого имени

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

  • Область действия пакета, заданная описанием пакета (package), определена базовой системой (§7.4.3). Весь код программы на языке Ява находится внутри области действия стандартного пакета, именуемого java, так что на пакет java всегда можно ссылаться из программы на Ява.
  • Область действия типа, импортированного описанием одиночного импорта типа или описанием импорта типа по шаблону (§7.5.2) , составляют все описания классовых типов и интерфейсных типов (§7.6) в модуле компиляции, где находится объявление импорта
  • Область действия типа введенного описанием классового типа (§8.1.1) или описанием интерфейсного типа (§9.1.1) , представляет собой описания всех классовых и интерфейсных типов во всех модулях компиляции (§7.3) пакета, в котором он объявлен.
  • Область действия члена, объявленного или унаследованного классовым (§8.2) или интерфейсным (§9.2) типами представляет собой всё описание класса или интерфейсного типа. Описание члена должно появиться перед его использованием только когда он используется в выражении инициализации поля (§8.3.2, §12.4.2, §12.5) . Это иллюстрируется тестовой программой, в результате работы которой возникает ошибка времени компиляции:

	class Test {
		int i = j;				// ошибка времени компиляции: некорректная опережающая ссылка
		int j = 1;
	}

тогда как следующий пример компилируется без ошибки:


	class Test {
		Test() { k = 2; }
		int j = 1;
		int i = j;
		int k;
	}

не смотря на то, что конструктор (§8.6) Test обращается к полю k, которое объявляется на три строки позже.

  • Область действия параметра метода (§8.4.1) представляет собой тело метода.
  • Область действия параметра конструктора (§8.6.1) представляет собой тело конструктора.
  • Область действия локальной переменной описанной в блоке (§14.3.2) представляет собой часть блока, в котором появляется описание, начинающуюся ее собственным инициализатором (§14.3) и включающую любые описания, расположенные правее в операторе описания локальной переменной.
  • Область действия локальной переменной объявленной в части ForInit оператора for (§14.12) включает следующее:
  • собственный инициализатор
  • любые дальнейшие описания правее части ForInit оператора for
  • части Expression и ForUpdate оператора for
  • содержащийся в Statement
  • Область действия параметра обработчика исключительных ситуаций, который объявлен в операторе catch оператора try (§14.18) представляет собой весь блок, ассоциированный с 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 Скрытые имена

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

Пример:


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.3.2); в данном случае это остаток метода main, а именно его инициализатор "0" и вызовы print и println.

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

  • Выражение "x" в вызове print обращается к значению локальной переменной x.
  • Вызов println использует квалифицированное имя (§6.6) Test.x, которое использует имя классового типа Test для доступа к переменной класса x, потому что описание Test.x в этой точке скрыто, к ней нельзя обратиться с помощью простого имени.

Если следовать стандартным соглашениям именования (§6.8) , то скрытие делает распознавание отдельных контекстов имени более сложным. Следующий пример включает скрытие, потому что он не следует стандартному соглашению присваивания имен:


class Point { int x, y; }

class Test {

	static Point Point(int x, int y) {
		Point p = new Point();
		p.x = x; p.y = y;
		return p;
	}


	public static void main(String[] args) {
		int Point;
		Point[] pa = new Point[2];
		for (Point = 0; Point < 2; Point++) {
			pa[Point] = new Point();
			pa[Point].x = Point;
			pa[Point].y = Point;
		}
		System.out.println(pa[0].x + "," + pa[0].y);
		System.out.println(pa[1].x + "," + pa[1].y);
		Point p = Point(3, 4);
		System.out.println(p.x + "," + p.y);
	}

}

Пример компилируется без ошибок и выводит на экран следующее:


0,0
1,1

3,4

Внутри тела main, при просмотре Point обнаруживаются различные описания в зависимости от контекста использования:

  • В выражении "new Point[2]", двух выражениях создания экземпляра класса "new Point()", и в начале трех различных выражений описания локальной переменной, Point это TypeName (§6.5.4) и указывает классовый тип Point в каждом случае.
  • В выражении вызова метода "Point(3, 4)" появление Point представляет собой MethodName (§6.5.6) и означает класс метода Point.
  • Все другие имена – это ExpressionNames (§6.5.5) и обращаются к локальной переменной Point.

Пример:

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.4 Члены и наследование

Пакеты и ссылочные типы содержат члены. Члены пакета (§7) , это подпакеты (§7.1) и все классовые (§8) и интерфейсные (§9) типы, объявленные во всех модулях компиляции (§7.3) пакета. Члены ссылочного типа (§4.3) - это поля (§8.3, §9.3, §10.7) методы (§8.4, §9.4) . Члены объявляются в типе, но могут быть унаследованы, потому что они являются доступными членами суперкласса или суперинтерфейса, и не являются ни скрытыми, ни переопределенными (§8.4.6).

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

6.4.1 Члены пакета

Член пакета (§7) - это либо подпакет (§7.1) , либо классовый (§8) или интерфейсный (§9) тип, объявленные в модуле компиляции пакета.

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

package vector;
public class Vector { Object[] vec; }

который имеет член public-класса, названный Vector, хотя стандартный пакет java.utill также объявляет класс Vector. Эти два класса типов различны и имеют различные полностью квалифицированные имена (§6.7) . Полностью квалифицированное имя Vector в данном примере, является vector.Vector, тогда как java.util.Vector представляет собой полностью квалифицированное имя стандартного класса Vector. Поскольку пакет vector содержит класс с именем Vector, он не может при этом иметь подпакет с именем Vector.

6.4.2 Члены классового типа

Члены классового типа (§8.2) - это поля и методы. Членами классового типа могут являться:

  • Члены, унаследованные от своего прямого суперкласса (§8.1.3) , если он есть (у класса Object нет прямого суперкласса).
  • Члены, унаследованные от любых прямых суперинтерфейсов (§8.1.4)
  • Члены, объявленные в теле класса (§8.1.5)

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

Отсутствуют ограничения, запрещающие полю и методу классового типа, иметь одно и то же простое имя.

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

В примере:


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

В этом примере, члены класса Point представляют собой переменные экземпляра x и y типа float, объявленные в Point, два объявленных метода move, объявленный метод toString, и члены, которые Point неявно наследует из своего прямого суперкласса Object (§4.3.2) , как, например, метод hashCode (§20.1.4) . Заметьте, что Point не наследует метод toString (§20.1.2) класса Object, потому что этот метод перегружается описанием метода toString в классе Point.

6.4.3 Члены интерфейсного типа

Члены интерфейсного типа (§9.2) - это поля и методы. Членами интерфейсного типа могут быть: 

  • Члены, унаследованные от любого прямого суперинтерфейса (§9.1.3)
  • Члены, объявленные в теле интерфейса (§9.1.4)

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

  • Члены, унаследованные от своего неявного суперкласса Object (§4.3.2, §20.1)
  • Поле length, которое представляет собой константное (final) поле каждого массива; его тип int, и он содержит число членов массива.

Пример:


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 или AmbiguousName (неоднозначное имя). Во-вторых, имя, которое изначально классифицируется своим контекстом в качестве AmbiguousName, переклассифицируется по определенным правилам области действия, чтобы представлять собой PackageName, TypeName или ExpressionName. В-третьих, результирующая категория указывает конечное определение значения имени (или ошибку времени компиляции, если имя не имеет значения).

    PackageName:
    
    	Identifier
    
    	PackageName . Identifier
    
    TypeName:
    
    	Identifier
    
    	PackageName . Identifier
    
    ExpressionName:
    
    	Identifier
    
    	AmbiguousName . Identifier
    
    MethodName:
    
    	Identifier
    
    	AmbiguousName . Identifier
    
    AmbiguousName:
    
    	Identifier
    
    	AmbiguousName . Identifier
    

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

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

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

  • В объявлении пакета (§7.4)
  • В описании импорт типа по шаблону (§7.5.2)
  • Слева от "." в квалифицированном PackageName
  • Слева от "." в квалифицированном TypeName

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

  • В описании одиночного импорта типа (§7.5.1)
  • В предложении extends в объявлении класса (§8.1.3)
  • В предложении implements в объявлении класса (§8.1.4)
  • В предложении extends в объявлении интерфейса (§9.1.3)
  • В качестве Type (или части Type, который остается после удаления всех скобок) в любом из следующих контекстах:
  • В объявлении поля (§8.3, §9.3)
  • Как тип результата метода (§8.4, §9.4)
  • Как тип формального параметра метода или конструктора (§8.4.1, §8.6.1, §9.4)
  • Как тип исключения, которое может генерироваться методом или конструктором (§8.4.4, §8.6.4, §9.4)
  • Как тип локальной переменной (§14.3)
  • Как тип параметра исключения в операторе catch оператора try (§14.18)
  • Как классовый тип экземпляра, который должен быть создан в выражении создания экземпляра класса (§15.8)
  • Как тип элемента массива, который создается выражением создания массива (§15.9)
  • Как тип упомянутый в операторе приведения выражения приведения (§15.15)
  • Как тип, который следует за операцией отношения instanceof (§15.19.2)

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

  • Как выражение обращения к массиву в выражении доступа к массиву (§15.12)
  • В качестве PostfixExpression (§15.13)
  • Как левый операнд оператора присваивания (§15.25)

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

  • Перед "(" в выражении вызова метода (§15.11)

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

  • Слева от "." в квалифицированном ExpressionName
  • Слева от "." в квалифицированном MethodName
  • Слева от "." в квалифицированном AmbiguousName

6.5.2 Переклассификация контекстно-неоднозначных имен

AmbiguousName переклассифицируетя в следующих случаях:

  • Если AmbiguousName представляет собой простое имя, состоящее из одного Identifier:
  • Если Identifier появляется внутри области действий (§6. 3) описания локальной переменной (§14.3) или описании параметра (§8.4.1, §8.6.1, §14.18) с этим именем, тогда AmbiguousName переклассифицируется как ExpressionName.
  • В противном случае, рассматривается класс или интерфейс C, внутри описания которого появляется Identifier. Если C имеет одно или несколько полей с тем же именем, которое может быть либо описано внутри него, либо унаследованным, тогда AmbiguousName переклассифицируется как ExpressionName.
  • Иначе если тип этого имени был описан в модуле компиляции (§7.3) содержащем Identifier либо описанием одиночного импорта типа (§7.5.1), либо описанием классового или интерфейсного типов (§7.6) , тогда AmbiguousName переклассифицируется как TypeName.
  • В противном случае, если тип этого имени описан в другом модуле компиляции (§7.3) пакета (§7.1) модуля компиляции, содержащего Identifier, тогда AmbiguousName переклассифицируется как TypeName.
  • Иначе, если тип этого имени объявлен описанием одиночного импорта типа по шаблону модуля компиляции (§7.5.2), содержащем Identifier, тогда AmbiguousName переклассифицируется как TypeName.
  • Иначе, если тип этого имени объявлен более чем одним описанием импорта типа по шаблону в модуле компиляции, содержащем Identifier, тогда результатом будет ошибка времени компиляции.
  • Иначе, AmbiguousName переклассифицируется как PackageName. Следующим шагом выясняется имеется ли фактически пакет с таким именем.
  • Если AmbiguousName представляет собой квалифицированное имя, состоящее из имени, ".", и Identifier, тогда имя слева от "." переклассифицируется, поскольку оно само AmbiguousName. Затем существует несколько вариантов:
  • Если имя слева от "." переклассифицируется как PackageName, тогда существует еще несколько вариантов:
  • если имеется пакет, имя которого совпадает с именем, стоящим слева от "." и этот пакет содержит описание типа, и имя этого типа совпадает с именем Identifier, тогда данное AmbiguousName переклассифицируется как TypeName.
  • в противном случае, AmbiguousName переклассифицируется как PackageName. Это определяется на более позднем шаге либо фактически не существует пакета с таким же именем.
  • Если имя слева от "." переклассифицируется как TypeName, тогда это AmbiguousName переклассифицируется как ExpressionName.
  • Если имя слева от "." переклассифицируется как ExpressionName, тогда это AmbiguousName переклассифицируется как ExpressionName.

В качестве примера рассмотрим следующий придуманный "библиотечный код":

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. Они затем переклассифицируются:

  • Предполагая, что отсутствует класс или интерфейс с именем ORG в любом другом модуле компиляции пакета bazola, простое имя ORG переклассифицируется как PackageName.
  • Далее, предполагаем, что класс или интерфейс с именем rpgpoet отсутствует в любом модуле компиляции пакета ORG (и мы знаем, что такого класса или интерфейса нет, потому что пакет ORG имеет подпакет с именем rpgpoet), квалифицированное имя ORG.rpgpoet переклассифицируется в PackageName.
  • Далее, поскольку пакет ORG.rpgpoet имеет интерфейсный тип с именем Music, квалифицированное имя ORG.rpgpoet.Music переклассифицируется в TypeName.
  • Наконец, поскольку имя ORG.rpgpoet.Music представляет собой TypeName, квалифицированное имя ORG.rpgpoet.Music.wizards переклассифицируется в ExpressionName.

6.5.3 Значение имен пакетов

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

6.5.3.1 Простые имена пакетов

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

6.5.3.2 Составные имена пакетов

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

6.5.4 Значение имен типов

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

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

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

  • Если тип с этим именем объявлен в текущем модуле компиляции (§7.3), любым описанием одиночного импорта типа (§7.5.1) или описанием классового или интерфейсного типа (§7.6), тогда простое имя типа означает этот тип.
  • Иначе, если тип с этим именем объявлен в другом модуле компиляции (§7.3) пакета (§7.1) содержащего идентификатор, тогда идентификатор означает этот тип. Стоит заметить, что в системах, которые хранят модули компиляции в файловой системе, такого рода модуль компиляции должен иметь имя файла, которое представляет собой имя типа (§7.6) .
  • В противном случае, если тип этого имени описан одиночным описанием импорта типа по шаблону (§7.5.2) модуля компиляции, содержащего идентификатор, тогда простое имя типа указывает этот тип.
  • Иначе, если тип того имени объявлен более чем одним описанием импорта типа по шаблону модуля компиляции, тогда имя неоднозначно в качестве имени типа; происходит ошибка времени компиляции.
  • В противном случае, имя не определено как имя типа; происходит ошибка времени компиляции.

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

6.5.4.2 Составные имена типов

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

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

В этом примере:

  • Имя wnj.test должно быть именем пакета в базовой системе. Это определяется при первом взгляде на пакет wnj, используя алгоритм, описанный в §6.5.3.1 , а затем убеждаемся, что подпакет test этого пакета доступен.
  • Имя java.util.Date (§21.3) должно указать тип, таким образом, мы первые используем алгоритм рекурсивного определения, если java.utill доступный пакет и затем смотрим, чтобы увидеть, доступен ли тип Date в этом пакете.

6.5.5 Значение имен выражения

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

6.5.5.1 Простые имена выражения

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

  • Если Identifier появляется внутри области действий описания (§6.3) локальной переменной (§14.3) или описания параметра (§8.4.1, §8.6.1, §14.18) с этим именем, тогда вид имени указывает переменную, то есть, локальную переменную либо параметр. Локальные переменные и параметры никогда не скрыты (§6.3, §6.3.1, §14.3) , таким образом обязательно должна быть более, чем одна такая локальная переменная, либо параметр. Тип имени выражения представляет собой объявленный тип локальной переменной или параметра.
  • Иначе, если Identifier появляется внутри описания класса (§8):
  • Если нет именно одного члена того класса (§8.2), который представляет собой поле с тем же именем, тогда результатом будет ошибка времени компиляции.
  • В противном случае, если единственный член поля с этим именем объявлен в конце (§8.3.1.2) , тогда имя выражения указывает значение поля. Тип имени выражения представляет собой объявленный тип поля. Если Identifier появляется в контексте, который требует переменной а не значения, тогда происходит ошибка времени компиляции.
  • Иначе, имя выражения указывает переменную, единственный член поля с этим именем. Тип имени выражения представляет собой тип объявленного поля.

Если поле - переменная экземпляра (§8.3.1.1), имя выражения должно появиться внутри описания метода экземпляра (§8.4), конструктора (§8.6), или инициализатора переменной экземпляра (§8.3.2.2). Если оно появляется внутри static-метода (§8.4.3.2), статического инициализатора (§8.5), или инициализатора для static-переменной (§8.3.1.1, §12.4.2), тогда происходит ошибка времени компиляции.

  • В противном случае, идентификатор появляется внутри описания интерфейса (§9):
  • Если нет именно одного члена того класса, который представляет собой поле с тем же именем, тогда результатом будет ошибка времени компиляции.
  • Иначе, имя выражения указывает значение единственного члена поля этого имени. Тип имени выражения представляет собой объявленный тип поля. Если Identifier появляется в контексте, который требует переменной и не имеет значения, тогда происходит ошибка времени компиляции.

В примере:


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 представляет собой final-переменную). Пример порождает ошибку времени компиляции, потому что последнее присваивание не содержит переменную с левой стороны. Если ошибочное присваивание устранено, модифицированный код может быть откомпилирован и будет выведено:

1 2 3

6.5.5.2 Квалифицированные имена выражения

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

  • Если Q представляет собой имя пакета, тогда происходит ошибка времени компиляции.
  • Если Q это имя типа, которое является именем классового типа (§8), тогда:
  • Если нет единственного доступного (§6.6) члена классового типа, являющегося полем с именем Id, тогда происходит ошибка времени компиляции.
  • В противном случае, если единственный доступный член поля, не является переменной класса (то есть, он не объявлен static), тогда происходит ошибка времени компиляции.
  • Иначе, если переменная класса объявлена final, тогда Q.Id задает значение переменной класса. Тип выражения Q.Id представляет собой объявленный тип переменной класса. Если Q.Id появляется в контексте, который требует переменной, а не значения, тогда происходит ошибка времени компиляции.
  • В противном случае, Q.Id указывает переменную класса. Тип выражения Q.Id представляет собой объявленный тип переменной класса.
  • Если Q есть имя типа, которое совпадает с именем интерфейсного типа (§9), тогда:
  • Если нет единственного доступного (§6.6) члена интерфейсного типа, который представляет собой поле с именем Id, тогда происходит ошибка времени компиляции.
  • Иначе, Q.Id указывает значение поля. Тип выражения Q.Id представляет собой объявленный тип поля. Если Q.Id появляется в контексте, который требует переменной, а не значения, тогда происходит ошибка времени компиляции.
  • Если Q имя выражения, пусть T будет тип выражения Q:
  • Если T не ссылочный тип, происходит ошибка времени компиляции.
  • Если нет единственного доступного (§6.6) члена типа T, который представляет собой область с именем Id, тогда происходит ошибка времени компиляции.
  • В противном случае, если это поле будет одним из следующих:
  • поле интерфейсного типа
  • final-поле классового типа (которое может быть либо переменной класса, либо переменной экземпляра)
  • final-поле length типа массив
  • тогда Q.Id указывает значение поля. Тип выражения Q.Id представляет собой объявленный тип поля. Если Q.Id появляется в контексте, который требует переменной, а не значения, тогда происходит ошибка времени компиляции.
  • Иначе, Q.Id указывает переменную, поле Id класса T, которой может быть либо переменная класса, либо переменная экземпляра. Тип выражения Q.Id представляет собой объявленный тип поля.

Пример:


class Point {
	int x, y;
	static int nPoints;
}

class Test {
	public static void main(String[] args) {
		int i = 0;
		i.x++;								// ошибка времени компиляции
		Point p = new Point();
		p.nPoints();								// ошибка времени компиляции
	}
}

встречаются две ошибки времени компиляции, потому что переменная i типа int не имеет членов, и потому что nPoints не является методом класса Point.

6.5.6 Значение имен методов

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

6.5.6.1 Простые имена методов

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

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

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

6.6 Квалифицированные имена и управление доступом

Квалифицированные имена - средства доступа к членам пакетов и ссылочных типов; средствами доступа являются выражения доступа к полю (§ 15.10) и выражения вызова метода (§ 15.11). Все три средства доступа синтаксически похожи тем, что появляется лексема “.”, которой предшествует некоторый указатель на пакет, тип или выражение, имеющее тип, за которой следует Identifier, и этот идентификатор является именем члена пакета или типа. Они все вместе известны как конструкции квалифицированного доступа.

Язык Ява предусматривает механизмы управления доступом, устраняющие зависимость пользователей, работающих с пакетами или классами, от деталей реализации этого пакета или класса. Управление доступом применяется к квалифицированному доступу и вызову конструкторов с помощью выражений создания экземпляров класса (§ 15.8), явных вызовов конструкторов (§ 8.6.5) и метода newInstance класса Class (§20.3.6).

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

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

  • Доступ к пакету определяется базовой системой (§ 7.2).
  • Если классовый или интерфейсный тип объявлен с модификатором доступа public, тогда он доступен в любом коде на языке Ява, который имеет доступ к пакету, в котором этот тип объявлен. Если классовый или интерфейсный тип не объявлен с модификатором доступа public, тогда к нему можно обратиться только в том пакете, в котором он объявлен.
  • Член (поле или метод) ссылочного типа (класса, интерфейса или массива) или конструктор классового типа доступен только в том случае, если тип общедоступен и к члену или конструктору при объявлении разрешен доступ:
  • Если член или конструктор объявлен с модификатором доступа public, тогда доступ к нему разрешен. Все члены интерфейсов по умолчанию имеют модификатор доступа public.
  • Иначе, если член или конструктор объявлен с модификатором доступа protected, тогда доступ разрешается, когда один из следующих пунктов является истинным:
  • Доступ к члену или конструктору происходит внутри пакета, содержащего класс, в котором объявлен член с модификатором доступа protected.
  • Доступ происходит в пределах подкласса класса, в котором объявлен член с модификатором доступа protected, и доступ является корректным, как описано в § 6.6.2.
  • Иначе, если член или конструктор объявлен с модификатором доступа private, тогда доступ к нему разрешается только внутри класса, в котором он объявлен.
  • Иначе мы говорим, что имеет место доступ по умолчанию, который разрешен только тогда, когда обращение происходит внутри пакета, в котором объявлен тип.

6.6.2 Модификатор доступа protected

Если член или конструктор объекта объявлен с модификатором доступа protected, то к нему можно обращаться вне пакета, в котором он объявлен только с помощью кода, ответственного за реализацию этого объекта. Пусть C - класс, в котором объявлен член или конструктор с модификатором доступа protected, и S - подкласс класса C, в котором используется этот член или конструктор с модификатором доступа protected. Тогда:

  • Если доступ осуществляется к члену (полю или методу) с модификатором protected, пусть Id - имя элемента. Тогда рассмотрим средства квалифицированного доступа:
  • Если доступ к полю осуществляется выражением вида super.Id, тогда доступ разрешается.
  • Если доступ осуществляется с помощью квалифицированного имени Q.Id, где Q - это TypeName, в данном случае доступ разрешается, тогда и только тогда, когда Q есть S или подкласс S.
  • Если доступ осуществляется с помощью квалифицированного имени Q.Id, где Q - это ExpressionName, в этом случае доступ разрешается тогда и только тогда, когда тип выражения Q есть S или подкласс S.
  • Если доступ к полю осуществляется с помощью выражения E.Id, где E классифицируется как Primary - выражение (первичное выражение), или выражением вызова метода E.Id (...), где E является Primary выражением, в этом случае доступ разрешен тогда и только тогда, когда тип E есть S или подкласс S.
  • Иначе, если доступ осуществляется к конструктору с модификатором доступа protected:
  • Если доступ осуществляется с помощью вызова конструктора суперкласса super(...), тогда доступ разрешается.
  • Если доступ осуществляется с помощью выражения создания экземпляра класса new T (...), тогда доступ не разрешается. (К конструктору с модификатором доступа protected можно обращаться, используя выражение создания экземпляра класса, только в пределах пакета, в котором он определен.)
  • Если доступ осуществляется вызовом метода newInstance класса Class (§ 20.3.6), тогда доступ не разрешается.

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:

  • Классовый тип PointVec не объявлен с модификатором доступа public и не является частью public-интерфейса пакета points, но может использоваться только другими классами пакета.
  • Классовый тип Point объявлен с модификатором доступа public и доступен другим пакетам. Это часть public-интерфейса пакета points.
  • Методы move, getX, и getY класса Point объявлены с модификатором доступа public и поэтому доступны любому коду на Яве, в котором используется объект типа Point.
  • Поля x и y объявлены с модификатором доступа protected и доступны вне пакета points только в подклассах класса Point, и только когда они являются полями объектов, которые реализуются с помощью кода, обращающегося к ним.

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

6.6.4 Пример: доступ к классам с модификаторами public и с модификаторами, не являющимися 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 доступен вне пакета, в то время как класс PointList доступен только в пределах пакета. Таким образом модуль компиляции другого пакета может иметь доступ к классу Point с помощью выражения 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 Пример: поля, методы и конструкторы c доступом по умолчанию

Если ни один из модификаторов доступа (public, protected или private) не указан, член или конструктор класса доступен во всем пакете, который содержит объявление класса, где данный член класса объявлен, но член или конструктор класса не доступен ни в каком другом пакете. Если 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);
	}
}

Так как метод move класса Point не перегружается методом move класса PlusPoint, метод moveAlso в Point никогда не вызывает метод move в 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);
    }

}

то она заканчивается успешно. Если метод move в Point был перегружен методом move в PlusPoint, тогда эта программа вызывала бы бесконечную рекурсию до тех пор, пока бы не произошла ошибка по переполнению стека.

6.6.6 Пример: поля, методы и конструкторы с модификатором public

Член или конструктор public-класса доступен в пакете, в котором он объявлен и в любом другом пакете, который имеет доступ к пакету, где содержится его объявление (§ 7.4.4). Например, в модуле компиляции:

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)						//ошибка времени компиляции: 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;						// ошибка времени компиляции: p.x не доступен
		p.y += this.y;						// ошибка времени компиляции: 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 и у) является подклассом Point (класс, в котором x и y объявлены) и не включает реализацию класса Point (тип параметра p). Метод delta3d может иметь доступ к членам параметра q, потому что класс Point3d является подклассом Point и включает реализацию класса Point3d.

В методе delta можно было бы попробовать привести (§ 5.4, § 15.15) параметр к Point3d, но это не помогло бы, приводя к исключению, если класс p во время выполнения не являлся бы Point3d.

В методе warp также происходит ошибка времени компиляции: невозможен доступ к полю z параметра а, потому что класс Point (класс, в котором происходит обращение к полю z) содержится в классе Point, (тип параметра a), но не является подклассом класса Point (класс, в котором объявлен z).

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

Член или конструктор класса с модификатором доступа 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.6.8 для примера, как используется конструктор с модификатором private.

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

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

  • Полностью определенное имя примитивного типа - это зарезервированное слово для этого примитивного типа, а именно 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[]".

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

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

Мы рекомендуем использовать эти соглашения во всех программах на языке Ява. Однако, не стоит слепо следовать этим правилам, если в вашем случае следует поступить иначе. Так, например, методы 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, зарезервированы для обозначения стандартных пакетов Ява-системы.

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

  • Если имя пакета скрывается объявлением поля, тогда обычно можно использовать import-объявления (§ 7.5) для того, чтобы сделать имя типа, объявленное в этом пакете, доступным.
  • Если имя пакета скрывается объявлением параметра или локальной переменной, тогда имя параметра или локальной переменной может быть изменено, не воздействуя на другой Ява-код.
  • Первый компонент имени пакета обычно не совпадает с именем типа, поскольку имя типа обычно начинается с одной буквы верхнего регистра. (язык Ява фактически не полагается на случайные различия, чтобы определить является ли имя именем пакета или именем типа. Для имени типа невозможно скрыть имя пакета.)

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

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


ClassLoader
SecurityManager
Thread
Dictionary
BufferedInputStream

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

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

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

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

  • Методы get и set для атрибута, который является переменной V должны быть getV и setV. Например - методы getPriority (§20.20.22) и setPriority (§20.20.23) классаjava.lang.Thread.
  • Метод, который возвращает длину чего-нибудь должен быть именован length, как в классе java.lang.String (§20.12.11).
  • Метод, который проверяет логическое значение V какого-то объекта должен быть именован isV. Например - метод isInterrupted класса java.lang.Thread (§20.20.32)
  • Метод, который преобразовывает объект в специфический формат F, должен быть именован toF. Например - метод toString класса java.lang.Objectt (§20.1.2) и методы toLocaleString (§21.3.27) и toGMTString (§21.3.28) класса java.util.Date.

Если всякий раз по возможности организовывать имена методов в новом классе, руководствуясь именами в уже существующем классе, который является подобным, особенно в классе из стандартных Java Application Programming Interface классов, то это облегчит их использование.

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

6.8.4 Имена полей.

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

Поля должны иметь имена, которые являются существительными, фразами с существительными, или аббревиатурами для существительных. Например – поля buf, pos и count класса java.io.ByteArrayInputStream (§22.6) и поле bytesTransferred класса java.io.InterruptedIOException (§22.30.1).

Скрытие имен полей очень редко.

  • Если имя поля скрывает имя пакета, тогда объявление import (§7.5) может обычно использоваться, чтобы сделать доступным имена типа, объявленные в этом пакете.
  • Если имя поля скрывает имя типа, тогда может использоваться полностью квалифицированное имя для типа.
  • Имена поля не могут скрывать имена метода.
  • Если имя поля скрыто объявлением параметра или локальной переменной, то имя параметра или локальной переменной может быть изменено без изменения кода Явы.

6.8.5 Имена констант.

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

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


interface ProcessStates {
	int PS_RUNNING = 0;
	int PS_SUSPENDED = 1;
}

Скрытие имен констант очень редко:

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

6.8.6 Локальная переменная и имена параметра.

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

  • Акронимы, которые являются первой буквой ряда слов, как cp для переменной, являющейся ссылкой на ColoredPoint .
  • Аббревиатуры, как buf, являющаяся указателем на buffer некоторого вида
  • Мнемонические термины, организованные некоторым способом, чтобы помочь запоминанию и пониманию, обычно, используют набор локальных переменных со стандартными именами по образцу имен параметров для широко используемых классов. Например:
  • in и out, всякий раз, когда предполагается некоторый ввод и вывод по образцу полей java.lang.System
  • off и len, всякий раз, когда предполагается смещение и длина по образцу параметров для методов чтения и записи интерфейсов DataInput и DataOutput of java.io

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

  • b для byte
  • c для char
  • d для double
  • e для исключения
  • f для float
  • i, j и k для целых чисел
  • l для long
  • O для Object
  • S для String
  • v для произвольного значения некоторого типа

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


[ Назад | Оглавление | Далее ]










helloworld.ru © 2001-2021
Все права защищены