Содержание | Предыдущий | Следующий | Индекс

ГЛАВА 6

Имена


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

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

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

У пакетов и ссылочных типов (то есть, типы классов, интерфейсные типы, и типы массива) есть элементы (§6.4). Элемент может быть отнесен в использование полностью определенного имени N.x, то, где N является простым или полностью определенным именем и x, является идентификатором. Если N называет пакет, то x является элементом того пакета, который является или классом или интерфейсным типом или подпакетом. Если N называет ссылочный тип или переменную ссылочного типа, то x называет элемент того типа, который является или полем или методом.

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

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

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

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

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

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

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

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

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

В примере:


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 Контекст Простого Имени

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


	class Test {
		int i = j;				// compile-time error: incorrect forward reference
		int j = 1;
	}

	class Test {
		Test() { k = 2; }
		int j = 1;
		int i = j;
		int k;
	}
Эти правила подразумевают, что объявления класса и интерфейсных типов не должны появиться перед использованием типов.

В примере:

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
Этот пример объявляет:

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

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

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

Если бы стандартные соглашения о присвоении имен (§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 найдите различные объявления в зависимости от контекста использования:

Пример:

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.3) пакета.

Вообще, подпакеты пакета определяются хост-системой (§7.2). Однако, стандартный пакет java всегда включает подпакеты lang, util, io, и net и может включать другие подпакеты. Ни у каких двух отличных элементов того же самого пакета не может быть того же самого простого имени (§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.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, тогда новое объявление, как говорят, реализует это; если метод, не наследованный, не 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 float переменные экземпляра x и y объявленный в 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) являются полями и методами. Элементы интерфейса являются всем следующим:

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

Пример:


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 Определение Значения Имени

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

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

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

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

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

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

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

Имя синтаксически классифицируется как 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.3), то ошибка времени компиляции происходит.

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

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

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

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

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

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

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

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

Если имя типа имеет форму Q.Идентификатор, тогда Q должен быть именем пакета. Имя типа Q.Идентификатор называет тип, который является элементом под названием Идентификатор в пределах пакета, названного Q. Если Q не называет доступный пакет, или Идентификатор не называет тип в пределах того пакета, или тип под названием Идентификатор в пределах того пакета не доступен (§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
В этом примере:

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

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

6.5.5.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.5.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.6 Значение Имен методов

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

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

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

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

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

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

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

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

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

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

6.6.2 Детали о protected Доступ

A protected к элементу или конструктору объекта можно получить доступ снаружи пакета, в котором он объявляется только кодом, который ответственен за реализацию того объекта. Позвольте C быть классом в который a protected элемент или конструктор объявляются и позволяются S быть подклассом C в чей объявлении использование 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 и не -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), который упоминает полностью qualfied имя, так, чтобы простое имя могло использоваться после того:


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.4.2) и тип возврата. Поскольку оригинал move метод не доступен от пакета morepoints, super возможно, не используется:


package morepoints;

public class PlusPoint extends points.Point {
	public void move(int dx, int dy) {
		super.move(dx, dy);								// compile-time error
		moveAlso(dx, dy);
	}
}
Поскольку перемещение Point не переопределяется move в PlusPoint, метод moveAlso в Point никогда не призывает перемещение метода PlusPoint.

Таким образом, если Вы удаляете super.move вызовите от PlusPoint и выполните тестовую программу:


import points.Point;

import morepoints.PlusPoint;

class Test {

    public static void main(String[] args) {
        PlusPoint pp = new PlusPoint();
        pp.move(1, 1);
    }

}
это обычно завершается. Если перемещение Point были переопределены move в PlusPoint, тогда эта программа рекурсивно вызвала бы бесконечно, до a StackoverflowError произошедший.

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

A 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 Поля, Методы, и Конструкторы

Рассмотрите этот пример, где point пакет объявляет:


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.4, §15.15) его параметр, чтобы быть a Point3d, но этот бросок перестал бы работать, вызывая исключение, если класс p во время выполнения не были Point3d.

Ошибка времени компиляции также происходит в деформации метода: это не может получить доступ к защищенному элементу z из его параметра a, потому что, в то время как класс Point (то класс, в который ссылка на поле z происходит), включается в реализацию a Point (тип параметра a), это не подкласс Point (то класс, в который 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, м.asterID, и setMasterID может использоваться только в пределах тела класса Point. К ним не могут получить доступ полностью определенные имена, выражения доступа к полю, или выражения вызова метода вне тела объявления Point.

См. §8.6.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[]".

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

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

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

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 резервируются к JavaSoft для того, чтобы назвать стандартные пакеты Java.

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

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

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


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

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

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

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

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

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

6.8.4 Имена полей

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

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

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

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 Локальная переменная и Названия параметра

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

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

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


Содержание | Предыдущий | Следующий | Индекс

Спецификация языка Java (HTML, сгенерированный Блинчиком "сюзет" Pelouch 24 февраля 1998)
Авторское право © Sun Microsystems, Inc 1996 года. Все права защищены
Пожалуйста, отправьте любые комментарии или исправления к doug.kramer@sun.com



Spec-Zone.ru - all specs in one place



free hit counter