Управление доступом к классам в пакетах. Пакетный уровень доступа к классу. Общедоступный (public) уровень доступа к классу

Управление доступом к классам в пакетах. Пакетный уровень доступа к классу. Общедоступный (public) уровень доступа к классу


Содержание



1. Какие причины в необходимости правильного управления доступом к содержимому библиотек на языке Java? Для чего нужно уметь правильно применять средства управления доступом?

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

2. Какие существуют уровни доступа к классам, размещенным в пакетах?

К классу, который есть частью пакета, есть два уровня доступа:

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

Манипулируя этими уровнями доступа, программист «скрывает» или предоставляет в общее пользование разработанный программный код для его дальнейшего использования другими разработчиками.

3. Что означает термин «пакетный» уровень доступа (package access)?

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

При пакетном уровне доступа член класса есть доступен другим классам текущего пакета. Для классов, которые реализованы в других пакетах, данный член класса считается скрытым или приватным (private).

4. Пример, который демонстрирует «пакетный уровень доступа для двух классов

В примере объявляется проект с именем DemoPackages. В проекте созданы 2 пакета с именами PackageA, PackageB. В пакете PackageA реализована библиотека из двух классов, которые имеют имена ClassA1 (размещается в модуле ClassA1.java) и ClassA2 (размещается в модуле ClassA2.java). Начальная структура проекта изображена на рисунке 1.

Рис. 1. Фрагмент окна Package Explorer. Структура пакета DemoPackages

Ниже приведены программные коды модулей (файлов) ClassA1.java, ClassA2.java, ClassB1.java, ClassB2.java которые соответствуют классам ClassA1, ClassA2, ClassB1, ClassB2.

Текст модуля ClassA1.java. В классе корректно создается объект класса ClassA2. Это логично, поскольку классы ClassA1 и ClassA2 объявлены в одном пакете и имеют доступ в пределах пакета.
Однако, попытка создать объект класса ClassB1 из другого пакета вызовет ошибку компиляции.

package PackageA;

class ClassA1 // нет явно заданного спецификатора public, доступ по умолчанию
{
    int a1;

    public static void main(String[] args)
    {
        // доступ к классу Class2 из класса Class1 - корректно, классы в одном пакете
        ClassA2 cA2 = new ClassA2();
        cA2.a2 = 109;

        // этот код не будет компилироваться: классы ClassA1 и ClassB1 в разных пакетах
        // PackageB.ClassB1 cB1 = new PackageB.ClassB1(); // ошибка!
    }
}

Текст модуля ClassA2.java. В классе корректно создается объект класса ClassA1, так как классы объявляются в одном пакете. Ну и конечно, доступиться к классу ClassB1 по сокращенному имени не выйдет, поскольку этот класс реализован в другом пакете (PackageB).

package PackageA;

class ClassA2 // нету явно заданного спецификатора public, доступ по умолчанию
{
    int a2;

    public static void main(String[] args)
    {
        // доступ из класса ClassA2 к классу ClassA1 - работает, оба класса в одном пакете
        ClassA1 cA1 = new ClassA1();
        cA1.a1 = 17;

        // PackageB.ClassB1 cB1 = new PackageB.ClassB1(); // а это ошибка компиляции, классы в разных пакетах
    }
}

Текст модуля ClassB1.java. В модуле корректно создается объект класса ClassB2, так как классы ClassB1, ClassB2 находятся в одном пакете PackageB, доступ к которым осуществляется по умолчанию. Попытка создать объект класса ClassA1 есть неудачной, поскольку класс ClassA1 объявлен в другом пакете и для него не задан модификатора доступа public.

package PackageB;

// нет явно заданного спецификатора public, доступ по умолчанию (в границах пакета)
class ClassB1
{
    double b1 = 12.44; // внутренняя переменная

    public static void main(String[] args)
    {
        // доступ к классу ClassB2 из класса ClassB1
        ClassB2 cB2 = new ClassB2();
        cB2.b2 = 230;

        // здесь возникнет ошибка компиляции:
        // PackageA.ClassA1 cA1 = new PackageA.ClassA1(); // ошибка, ClassA1 объявляется в другом пакете
    }
}

Текст модуля ClassB2.java. В классе корректно инициализируется переменная класса ClassB1 так как классы ClassB1 и ClassB2 находятся в одном пакете.

package PackageB;

// нет явно заданного спецификатора public, доступ по умолчанию (в границах пакета)
class ClassB2
{
    int b2; // внутренняя переменная

    // инициализация работает, так как классы в одном пакете PackageB
    ClassB1 cB1 = new ClassB1();
}

5. Какие преимущества дает использование доступа в пределах пакета (по умолчанию)?

Доступ в пределах пакета дает следующие преимущества:

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

6. Что значит тип доступа public для класса реализованного в пакете?

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

package PackageName;

// ...

// объявление общедоступного класса
public class ClassName
{
    // ...
}

После такого объявления можно обратиться к классу в пакете из другого пакета с помощью вызова:

PackageName.ClassName

где PackageName – имя пакета, в котором реализован public-класс с именем PackageName.

В пакете может быть объявлено не большее одного public-класса.

7. Пример, который демонстрирует использование модификатора public для класса в пакете

Пусть в проекте с именем DemoAccess созданы два пакета с именами PackageA и PackageB. В пакете PackageA реализован класс ClassA, который имеет тип пакетный тип доступа (без модификатора доступа). В пакете PackageB реализован класс ClassB, который объявлен с модификатором public.

Структура проекта DemoAccess изображена на рисунке 2.

Рис. 2. Структура проекта DemoAccess

Текст класса ClassA из пакета PackageA следующий.

package PackageA;

// класс объявлен как пакетный (без модификатора public)
class ClassA
{
    public static void main(String[] args)
    {
        // Доступ к классу ClassB из пакета PackageB
        // работает, так как класс PackageB.ClassB объявлен как public
        PackageB.ClassB cB = new PackageB.ClassB();

        cB.b = 40; // работает, так как переменная b класса Class объявлена как public
    }
}

Как видно из вышеприведенного кода, можно без проблем доступиться к классу PackageB.ClassB, так как этот класс объявлен с модификатором доступа public.

Текст модуля ClassB.java, в котором реализован класс ClassB

package PackageB;

public class ClassB
{
    public int b = 20; // общедоступная переменная класса

    public static void main(String[] args)
    {
        // доступиться к классу PackageA.ClassA нельзя, поэтому он объявленн как пакетный
        // PackageA.ClassA cA = new PackageA.ClassA(); - ошибка компиляции
    }
}

Как видно из вышеприведенного кода, доступиться к классу PackageA.ClassA не удастся, так как этот класс объявлен как пакетный (без модификатора доступа).

Важно. Для того, чтобы доступиться к внутренней переменной b класса ClassB из методов класса ClassA, эта переменная должна быть объявлена с модификатором доступа public.

8. Можно ли в объявлении имени класса добавлять модификатор доступа private?

Нет. Язык Java не поддерживает использование модификатора доступа private перед именем класса. То есть, следующий код есть ошибочным

// слово private запрещено
private class ClassName
{
    // ...
}

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

// пакетный уровень доступа к классу
class ClassName
{
    // ...
}

9. Можно ли в объявлении имени класса добавлять модификатор доступа protected?

Нет, нельзя. Модификатор доступа protected применяется для классов, которые предоставляют свои члены данных и методы для унаследованных классов. В унаследованных классах protected-члены данных можно использовать, однако их нельзя использовать из объектов этих классов (извне). Но это уже совсем другая тема.


Связанные темы