Чтение онлайн

на главную - закладки

Жанры

Программирование на Java

Вязовик Н.А.

Шрифт:

Разграничение доступа в Java

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

В Java модификаторы доступа указываются для:

* типов (классов и интерфейсов) объявления верхнего уровня;

* элементов ссылочных типов (полей, методов, внутренних типов);

* конструкторов классов.

Как следствие, массив также может быть недоступен в том случае, если недоступен

тип, на основе которого он объявлен.

Все четыре уровня доступа имеют только элементы типов и конструкторы. Это:

* public;

* private;

* protected;

* если не указан ни один из этих трех типов, то уровень доступа определяется по умолчанию (default).

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

Наконец, protected дает доступ наследникам класса. Понятно, что наследникам может потребоваться доступ к некоторым элементам родителя, с которыми не приходится иметь дело внешним классам.

Однако описанная структура не позволяет упорядочить модификаторы доступа так, чтобы каждый следующий строго расширял предыдущий. Модификатор protected может быть указан для наследника из другого пакета, а доступ по умолчанию допускает обращения из классов-ненаследников, если они находятся в том же пакете. По этой причине возможности protected были расширены таким образом, что он включает в себя доступ внутри пакета. Итак, модификаторы доступа упорядочиваются следующим образом (от менее открытых – к более открытым):

private

(none) default

protected

public

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

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

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

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

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

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

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

только для наследников, также не были признаны полезными.

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

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

public class Wheel {

private double radius;

public double getRadius {

return radius;

}

}

Значение поля radius недоступно снаружи класса, однако открытый метод getRadius корректно возвращает его.

Рассмотрим следующие два модуля компиляции:

package first;

// Некоторый класс Parent

public class Parent {

}

package first;

// Класс Child наследуется от класса Parent,

// но имеет ограничение доступа по умолчанию

class Child extends Parent {

}

public class Provider {

public Parent getValue {

return new Child;

}

}

К методу getValue класса Provider можно обратиться и из другого пакета, не только из пакета first, поскольку метод объявлен как public. Данный метод возвращает экземпляр класса Child, который недоступен из других пакетов. Однако следующий вызов является корректным:

package second;

import first.*;

public class Test {

public static void main(String s[])

{

Provider pr = new Provider;

Parent p = pr.getValue;

System.out.println(p.getClass.getName);

// (Child)p - приведет к ошибке компиляции!

}

}

Результатом будет:

first.Child

То есть на самом деле в классе Test работа идет с экземпляром недоступного класса Child, что возможно, поскольку обращение к нему делается через открытый класс Parent. Попытка же выполнить явное приведение вызовет ошибку. Да, тип объекта "угадан" верно, но доступ к закрытому типу всегда запрещен.

Следующий пример:

public class Point {

private int x, y;

public boolean equals(Object o) {

if (o instanceof Point) {

Point p = (Point)o;

return p.x==x && p.y==y;

}

return false;

}

}

В этом примере объявляется класс Point с двумя полями, описывающими координаты точки. Обратите внимание, что поля полностью закрыты – private. Далее попытаемся переопределить стандартный метод equals таким образом, чтобы для аргументов, являющихся экземплярами класса Point, или его наследников (логика работы оператора instanceof ), в случае равенства координат возвращалось истинное значение. Обратите внимание на строку, где делается сравнение координат,– для этого приходится обращаться к private -полям другого объекта!

Поделиться:
Популярные книги

Звездная Кровь. Экзарх I

Рокотов Алексей
1. Экзарх
Фантастика:
боевая фантастика
рпг
фэнтези
фантастика: прочее
попаданцы
5.00
рейтинг книги
Звездная Кровь. Экзарх I

Сердце Дракона. нейросеть в мире боевых искусств (главы 1-650)

Клеванский Кирилл Сергеевич
Фантастика:
фэнтези
героическая фантастика
боевая фантастика
7.51
рейтинг книги
Сердце Дракона. нейросеть в мире боевых искусств (главы 1-650)

Девочка из прошлого

Тоцка Тала
3. Айдаровы
Любовные романы:
современные любовные романы
5.00
рейтинг книги
Девочка из прошлого

Барон диктует правила

Ренгач Евгений
4. Закон сильного
Фантастика:
фэнтези
попаданцы
аниме
5.00
рейтинг книги
Барон диктует правила

Ваантан

Кораблев Родион
10. Другая сторона
Фантастика:
боевая фантастика
рпг
5.00
рейтинг книги
Ваантан

Проводник

Кораблев Родион
2. Другая сторона
Фантастика:
боевая фантастика
рпг
7.41
рейтинг книги
Проводник

Белые погоны

Лисина Александра
3. Гибрид
Фантастика:
фэнтези
попаданцы
технофэнтези
аниме
5.00
рейтинг книги
Белые погоны

Последний попаданец

Зубов Константин
1. Последний попаданец
Фантастика:
фэнтези
попаданцы
рпг
5.00
рейтинг книги
Последний попаданец

Наследник

Кулаков Алексей Иванович
1. Рюрикова кровь
Фантастика:
научная фантастика
попаданцы
альтернативная история
8.69
рейтинг книги
Наследник

Антимаг

Гедеон Александр и Евгения
1. Антимаг
Фантастика:
фэнтези
6.95
рейтинг книги
Антимаг

Моя Академия

Листратов Валерий
1. Академка
Фантастика:
попаданцы
сказочная фантастика
фэнтези
4.50
рейтинг книги
Моя Академия

Я все еще граф. Книга IX

Дрейк Сириус
9. Дорогой барон!
Фантастика:
боевая фантастика
попаданцы
аниме
5.00
рейтинг книги
Я все еще граф. Книга IX

Медиум

Злобин Михаил
1. О чем молчат могилы
Фантастика:
фэнтези
7.90
рейтинг книги
Медиум

Последний Паладин. Том 5

Саваровский Роман
5. Путь Паладина
Фантастика:
фэнтези
попаданцы
аниме
5.00
рейтинг книги
Последний Паладин. Том 5