Java предоставляет явные модификаторы доступа для управления доступностью членов класса из внешних клиентов, но в двух случаях доступ управляется специальными правилами области видимости.
Область видимости класса (class scope) касается доступности членов (включая унаследованные) из кода внутри класса. В табл. 4.1 дается обзор того, как из статического и нестатического кода в классе можно получить доступ к членам класса, включая унаследованные. В табл. 4.1 предполагаются следующие объявления.
class SuperName {
int instanceVarInSuper;
static int staticVarInSuper;
void instanceMethodInSuper() { /* ... */ }
static void staticMethodInSuper() { /* ... */ }
// ...
}
class ClassName extends SuperName {
int instanceVar;
static int staticVar;
void instanceMethod() { /* ... */ }
static void staticMethod() { /* ... */ }
// ...
}
Есть главный принцип о том, что из статического кода нельзя получить доступ к нестатическим членам по их простым именам. Статический код не выполняется в контексте объекта, поэтому ссылки this
и super
недоступны. Объект, в свою очередь, хранит информацию о своем классе, поэтому к статическим членам из нестатического контекста всегда можно получить доступ.
Обратите внимание, что использование имени класса для доступа к статическим членам внутри класса не отличается от того, как внешние клиенты обращаются к статическим членам.
Некоторые факторы, которые могут повлиять на видимость члена:
Объявления | Нестатический код может ссылаться на | Статический код может ссылаться на |
---|---|---|
Переменные экземпляра | instanceVar | |
this.instanceVar | Not possible | |
instanceVarInSuper | ||
this.instanceVarInSuper | ||
super.instanceVarInSuper | ||
Методы экземпляра | instanceMethod() | |
this.instanceMethod() | ||
instanceMethodInSuper() | Not possible | |
this.instanceMethodInSuper() | ||
super.instanceMethodInSuper() | ||
Статические переменные | staticVar | staticVar |
this.staticVar | ||
ClassName.staticVar | ClassName.staticVar | |
staticVarInSuper | staticVarInSuper | |
this.staticVarInSuper | ||
super.staticVarInSuper | ||
ClassName.staticVarInSuper | ClassName.staticVarInSuper | |
SuperName.staticVarInSuper | SuperName.staticVarInSuper | |
Статические методы | staticMethod() | staticMethod() |
this.staticMethod() | ||
ClassName.staticMethod() | ClassName.staticMethod() | |
staticMethodInSuper() | staticMethodInSuper() | |
this.staticMethodInSuper() | ||
super.staticMethodInSuper() | ||
ClassName.staticMethodInSuper() | ClassName.staticMethodInSuper() | |
SuperName.staticMethodInSuper() | SuperName.staticMethodInSuper() |
Внутри класса C
ссылочные переменные типа C
могут использоваться для доступа ко всем членам в классе C
, несмотря на их модификаторы доступа. В примере 4.6 метод duplicateLight
в строке (1) в классе Light
содержит параметр oldLight
и локальную переменную newLight
, которые ссыпаются на объект Light
. Даже если поля класса имеют модификатор доступа private, они доступны по двум ссылкам (oldLight
и newLight
) в методе duplicateLight()
, что показано в строках (2), (3), и (4).
class Light {
// Instance variables
private int noOfWatts; // Мощность
private boolean indicator; // Включено или выключено
private String location; // Размещение
// Instance methods
public void switchOn() { indicator = true; }
public void switchOff() { indicator = false; }
public boolean isOn() { return indicator; }
public static Light duplicateLight(Light oldLight) { // (1)
Light newLight = new Light();
newLight.noOfWatts = oldLight.noOfWatts; // (2)
newLight.indicator = oldLight.indicator; // (3)
newLight.location = oldLight.location; // (4)
return newLight;
}
}
Объявления и операторы могут быть объединены в блок с помощью фигурных скобок {}
. Блоки могут быть вложенными, и к объявлениям локальных переменных в таких блоках применяются определенные правила. Локальное объявление может появиться в любом месте в блоке. Универсальное правило гласит, что переменная, объявленная в блоке, находится в зоне видимости блока, в котором объявлена, она недоступна извне блока. Нет возможности переобъявить переменную, если локальная переменная с таким именем уже объявлена в текущем контексте.
Локальные переменные метода — это формальные параметры метода и переменные, которые объявлены в теле метода. Локальные переменные в методе отличаются при каждом вызове и имеют свою собственную область хранения.
Тело метода является блоком. Параметры не могут быть переобъявлены в теле метода, как показано в строке (1) в блоке 1 (см. пример 4.6(б)).
Локальная переменная — переменная, объявленная в объемлющем блоке и поэтому видимая во вложенных блоках, — не может быть переопределена во вложенном блоке. Это иллюстрируется в строках (3), (5) и (6).
Локальная переменная может быть переопределена в другом блоке, если блоки разделены, т.е. они не перекрываются. Такой случай показан на примере переменной i
в строке (2) в блоке 3 и в строке (4) в блоке 4, так как эти блоки разделены.
Область видимости переменной начинается с места, где она определена, и заканчивается, как только этот блок завершается. Область видимости переменной цикла index
— это блок 2. Хотя блок 2 вложен в блок 1, объявление переменной index
в (7) в блоке 1 допустимо. Ее видимость простирается с момента ее объявления и до конца этого блока, и она не перекрывается с переменной цикла index
в блоке 2.
public static void main(String args[]) { // Блок 1
// String args = "";
char digit = 'z';
for (int index = 0; index < 10; ++index) { // Блок 2
switch (digit) { // Блок 3
case 'a':
int i; // (2)
default:
// int i; // (3) уже объявлена в этом блоке
} //switch
if (true) { // Блок 4
int i; // (4) Ok
// int digit; // (5) уже объявлена в объемлющем блоке 1
// int index; // (6) уже объявлена в объемлющем блоке 2
} // if
} // for
int index; //(7) Ok
} // main
Конструкторы | Пакеты |