Лекции.Орг


Поиск:




Категории:

Астрономия
Биология
География
Другие языки
Интернет
Информатика
История
Культура
Литература
Логика
Математика
Медицина
Механика
Охрана труда
Педагогика
Политика
Право
Психология
Религия
Риторика
Социология
Спорт
Строительство
Технология
Транспорт
Физика
Философия
Финансы
Химия
Экология
Экономика
Электроника

 

 

 

 


Локальные и глобальные переменные. Модификаторы доступа и правила видимости. Ссылка this




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

- Во-первых, при вызове в списке параметров не видно, что идёт обращение к соответствующим переменным, и программа становится “непрозрачной” для программиста. Что делает её неструктурной.

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

Конечно, бывают случаи, когда использование глобальных переменных не только желательно, а просто необходимо – иначе их не стали бы вводить как конструкцию языков программирования! Например, при написании метода в каком-либо классе обычно необходимо получать доступ к полям и методам этого класса. В Java такой доступ осуществляется напрямую, без указания имени объекта или класса.

Правила доступа к методам и полям данных (переменным) из других пакетов, классов и объектов задаются с помощью модификаторов private, protected, public. Правила доступа часто называются также правилами видимости, это синонимы. Если переменная или подпрограмма невидимы в некой области программы, доступ к ним запрещён.

private - элемент (поле данных или метод) доступен только в методах данного класса. Доступа из объектов нет! То есть если мы создали объект, у которого имеется поле или метод private, то получить доступ к этому полю или методу из объекта нельзя.

Модификатор не задан - значит, действует доступ по умолчанию – так называемый пакетный, когда соответствующий элемент доступен только из классов своего пакета. Доступа из объектов нет, если они вызываются в операторах, расположенных в классах из других пакетов!

Иногда, по аналогии с C++, этот тип доступа называют “дружественным”.

protected - элемент доступен только в методах данного класса, данного пакета, а также классах-наследниках (они могут располагаться в других пакетах).

public - элемент доступен из любых классов и объектов (с квалификацией именем пакета, если соответствующий класс не импортирован).

Например, в классе

class Vis1 {

private int x=10,y=10;

int p1=1;

protected int p2=1;

public int p3=1;

}

заданы переменные x,y,p1,p2,p3. Причём x и y обладают уровнем доступа private, p1 – пакетным, p2 – protected, p3 – public. Перечисление однотипных переменных через запятую позволяет использовать для нескольких переменных однократное задание имени типа и модификаторов, без повторений.

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

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

Ещё одной важной особенностью локальных переменных является время их существования: под них выделяется память в момент вызова, а высвобождается сразу после окончания вызова. Рассмотрим функцию, вычисляющую сумму чисел от 1 до n:

 

double sum1(int n){

int i;

double r=0;

for(i=1;i<=n;i++){

r+=i;

};

return r;

}

 

Вызов данного метода может выглядеть так:

c=obj1.sum1(1000);

При этом переменные i и r существуют только во время вызова obj1.sum1(1000). При следующем аналогичном вызове будет создан, а затем высвобожден из памяти следующий комплект i и r.

Всё сказанное про локальные переменные также относится и к объектным переменным. Но не следует путать переменные и объекты: время жизни объектов гораздо больше. Даже если объект создаётся во время вызова подпрограммы, а после окончания этого вызова связь с ним кончается. Уничтожением неиспользуемых объектов занимается сборщик мусора (garbage collector). Если же объект создан в подпрограмме, и ссылка на него передана какой-либо глобальной переменной, он будет существовать после выхода из подпрограммы столько времени, сколько необходимо для работы с ним.

Остановимся на области видимости локальной переменной. Имеются следующие уровни видимости:

- На уровне метода. Переменная видна от места декларации до конца метода.

- На уровне блока. Если переменная задана внутри блока {…}, она видна от места декларации до конца блока. Блоки могут быть вложены один в другой с произвольным уровнем вложенности.

- На уровне цикла for. Переменная видна от места декларации в секции инициализации до конца тела цикла.

Глобальные переменные видны во всей подпрограмме.

Каждый объект имеет поле данных с именем this (“этот” – данное не слишком удачное обозначение унаследовано из C++), в котором хранится ссылка на сам этот объект. Поэтому доступ в методе объекта к полям и методам этого объекта может осуществляться либо напрямую, либо через ссылку this на этот объект. Например, если у объекта имеется поле x и метод show(), то this.x означает то же, что x, а this.show() – то же, show(). Но в случае перекрытия области видимости, о чём речь пойдёт чуть ниже, доступ по короткому имени оказывается невозможен, и приходится использовать доступ по ссылке this. Отметим, что ссылка this позволяет обойтись без использования имени объектной переменной, что делает код с её использованием более универсальным. Например, использовать в методах того класса, экземпляром которого является объект.

Ссылка this не может быть использована в методах класса (то есть заданных с модификатором static), поскольку они могут вызываться без существующего объекта.

Встаёт вопрос о том, что произойдёт, если на разных уровнях будет задано две переменных с одним именем. Имеется следующие варианты ситуаций:

- В классе имеется поле с некоторым именем (глобальная переменная), и в списке параметров задаётся локальная переменная с тем же именем. Такая проблема часто возникает в конструкторах при инициализации полей данных и в методах установки значений полей данных setИмяПоля. Это разрешено, и доступ к параметру идёт по имени, как обычно. Но при этом видимость поля данных (доступ к полю данных по его имени) перекрывается, и приходится использовать ссылку на объект this. Например, если имя поля данных x, и имя параметра в методе тоже x, установка значения поля выглядит так:

void setX(double x){

this.x=x

}

- В классе имеется поле с некоторым именем (глобальная переменная), и в методе задаётся локальная переменная с тем же именем. Ситуация разрешена и аналогична заданию локальной переменной в списке параметров. Доступ к полю идёт через ссылку this.

- В классе имеется поле с некоторым именем (глобальная переменная), и в секции инициализации цикла for или внутри какого-нибудь блока, ограниченного фигурными скобками {…}, задаётся локальная переменная с тем же именем. В Java такая ситуация разрешена. При этом внутри цикла или блока доступна заданная в нём локальная переменная, а глобальная переменная видна через ссылку this.

- Имеется локальная переменная (возможно, заданная как элемент списка параметров), и в секции инициализации цикла for или внутри какого-нибудь блока, ограниченного фигурными скобками {…}, задаётся локальная переменная с тем же именем. В Java такая ситуация запрещена. При этом выдаётся ошибка компиляции с информацией, что переменная с таким именем уже задана (“is already defined”).

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

 





Поделиться с друзьями:


Дата добавления: 2017-02-28; Мы поможем в написании ваших работ!; просмотров: 605 | Нарушение авторских прав


Поиск на сайте:

Лучшие изречения:

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

2507 - | 2379 -


© 2015-2025 lektsii.org - Контакты - Последнее добавление

Ген: 0.011 с.