Menu

Модификаторы доступа в Java: public, private, protected, default

Как четыре уровня доступа в Java - public, private, protected и package-private - управляют тем, что другой код может видеть и трогать.

На этой странице есть исполняемые редакторы: меняйте, запускайте и сразу видите результат.

Кому позволено трогать ваш код

Модификатор доступа - это ключевое слово перед классом, полем, методом или конструктором, которое решает, кому ещё разрешено его использовать. Это основа инкапсуляции: вы прячете беспорядочные внутренности класса и открываете лишь те части, которые доверяете вызывать другому коду.

В Java четыре уровня, от самого открытого до самого закрытого: public, protected, default (вообще без ключевого слова) и private. Если выбрать их правильно, класс становится безопасным для последующих изменений, потому что ничто снаружи не зависит от деталей, сохранять которые вы никогда не обещали.

private: виден только внутри класса

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

balance является private, поэтому единственный способ изменить его - через deposit, который отвергает отрицательные суммы. Если бы balance был public, любой код мог бы написать account.balance = -9999 и полностью обойти проверку. Эта защита - и есть весь смысл сокрытия поля.

Попробуйте раскомментировать account.balance = 500; в main, и вы получите ошибку компиляции: balance has private access in BankAccount.

public: виден везде

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

Распространённый шаблон - иногда называемый публичным API класса - таков: приватные поля, публичные методы. Поля хранят состояние, в которое никто другой не должен лезть; методы - это контролируемые двери внутрь и наружу. getBalance и deposit выше - именно это.

default (package-private): вообще без ключевого слова

Если вы не пишете никакого модификатора, вы получаете default доступ, который также называют package-private. Член виден всем классам в том же пакете и невидим всему, что за его пределами. Для этого уровня нет ключевого слова - отсутствие его и есть уровень.

class Invoice {       // нет модификатора -> виден только внутри этого пакета
    int amount;       // нет модификатора -> поле package-private
}

На этом попадается множество новичков: опустить public не значит сделать что-то private, это делает его package-private. Поле, которое вы хотели сохранить в секрете, всё ещё полностью доступно для чтения и записи любым классом, который оказался в том же пакете. Если вы хотите, чтобы оно было действительно скрыто, нужно явно написать private.

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

protected: пакет плюс подклассы

protected на одну ступень свободнее, чем default. protected член виден везде, где виден default (тот же пакет), а также в подклассах - даже в подклассах из другого пакета. Он предназначен для того, чем вы хотите поделиться с классами, расширяющими ваш, но не со всем миром.

Dog обращается к name и sound(), потому что они protected, а Dog - подкласс. Внешний код, который не является подклассом и не находится в пакете, по-прежнему не может их трогать. Прибегайте к protected, когда проектируете класс, предназначенный для расширения; в остальных случаях предпочитайте private.

Четыре уровня с одного взгляда

Вот полная картина, от самого ограничивающего до самого открытого:

МодификаторТот же классТот же пакетПодкласс (другой пакет)Везде
privateданетнетнет
defaultдаданетнет
protectedдададанет
publicдададада

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

Модификаторы у самих классов

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

public class Order { ... }   // доступен из любого пакета
class LineItem { ... }       // default - виден только этому пакету

Класс верхнего уровня public должен находиться в файле, названном по его имени (Order.java). Вложенные же классы могут использовать все четыре модификатора - именно поэтому примеры выше могли помечать внутренние классы как private или default. Тонкий момент: public метод, возвращающий тип package-private, не очень полезен для внешних вызывающих, поэтому сохраняйте публичную поверхность согласованной.

Далее: статические члены

До сих пор каждое поле и метод здесь принадлежат экземпляру - вы создаёте объект через new, а затем вызываете на нём методы. Но иногда значение или поведение принадлежит классу в целом, общему для всех экземпляров, - например, счётчик того, сколько объектов существует. Именно для этого нужно ключевое слово static, и оно идёт следующим.

Часто задаваемые вопросы

Какие четыре модификатора доступа есть в Java?

public, private, protected и default (без ключевого слова, его ещё называют package-private). public виден везде, private - только внутри того же класса, protected - внутри пакета плюс в подклассах, а default - только внутри того же пакета.

В чём разница между public и private в Java?

public означает, что любой код где угодно может обратиться к члену. private означает, что это может сделать только код внутри того же класса - подклассы и другие классы его даже не видят. Обычно поля делают private и открывают доступ к ним через public методы.

Что значит, если у поля в Java нет модификатора доступа?

Отсутствие ключевого слова означает default (package-private) доступ: член виден всем классам в том же пакете, но невидим за его пределами. Это строже, чем public, но свободнее, чем private - и его легко опустить по случайности, поэтому подходите к этому осознанно.

Coddy programming languages illustration

Учитесь программировать с Coddy

НАЧАТЬ