Public, protected, private и package-private в Java: полный разбор

Онлайн-тренажер Python для начинающих

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

Начать курс

Что скрывают модификаторы доступа в Java? Погружение в инкапсуляцию

Каждый, кто начинал изучать Java, сталкивался с загадочными словами public, private и protected перед полями и методами. Но что они на самом деле значат? Почему нельзя просто сделать всё public и жить спокойно? И что это за таинственный package-private, о котором молчат в большинстве туториалов?

В этой статье мы разберём разницу между public, protected, package-private и private в Java на реальных примерах с кодом. Вы узнаете, как работает каждый модификатор, в каких ситуациях их применять, и почему правильный выбор модификатора доступа — признак хорошего архитектурного мышления. Поехали!

Зачем вообще нужны модификаторы доступа?

Представьте, что вы строите дом. У вас есть входная дверь (доступна всем), комната для гостей (доступна друзьям), личный кабинет (только для семьи) и сейф (только для вас). Модификаторы доступа в Java работают точно так же: они определяют, кто может «войти» в ваш класс, метод или поле.

Основная цель — инкапсуляция. Мы прячем внутренние детали реализации класса и предоставляем наружу только то, что действительно нужно. Это защищает данные от случайного изменения и упрощает поддержку кода.

Краткий обзор четырёх уровней доступа

В Java существует четыре уровня доступа (от самого строгого к самому открытому):

  • private — доступ только внутри класса
  • package-private (по умолчанию) — доступ внутри класса и пакета
  • protected — класс + пакет + наследники
  • public — доступ отовсюду

Private: «Моё — и ничьё больше»

Модификатор private — самый строгий. Поле или метод, помеченное как private, доступно только внутри того же класса. Ни наследники, ни классы из того же пакета не могут к нему обратиться.

public class BankAccount {
    private double balance;  // Доступен только внутри класса

    public BankAccount(double initialBalance) {
        this.balance = initialBalance;
    }

    public void deposit(double amount) {
        if (amount > 0) {
            balance += amount;
        }
    }

    // Этот метод видит private поле, потому что он внутри класса
    public double getBalance() {
        return balance;
    }
}

public class Main {
    public static void main(String[] args) {
        BankAccount account = new BankAccount(1000);
        // account.balance = 5000;  // Ошибка компиляции! balance — private
        System.out.println(account.getBalance());  // Работает через публичный метод
    }
}

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

Package-private (default): «Тихий сосед»

Если вы не указали никакой модификатор, Java автоматически делает доступ package-private. Это означает, что поле или метод видны всем классам внутри того же пакета, но не видны за его пределами.

package com.pythonlib.utils;

class Helper {  // package-private класс (без модификатора)
    String secretMessage = "Видно только внутри пакета";  // package-private поле

    void displayMessage() {  // package-private метод
        System.out.println(secretMessage);
    }
}

package com.pythonlib.app;

import com.pythonlib.utils.Helper;

public class App {
    public static void main(String[] args) {
        Helper helper = new Helper();
        // helper.secretMessage = "Ошибка!";  // Не видно — другой пакет
        // helper.displayMessage();  // Ошибка компиляции
    }
}

Когда использовать: для служебных классов и методов, которые используются только внутри вашего модуля/пакета. Это отличный способ скрыть реализацию от внешнего мира, не заморачиваясь с private.

Protected: «Семейный доступ»

Модификатор protected — золотая середина. Он даёт доступ:

  • Внутри класса
  • Всем классам в том же пакете
  • Наследникам из других пакетов (но только через наследование)
package com.pythonlib.animals;

public class Animal {
    protected String species = "Млекопитающее";

    protected void makeSound() {
        System.out.println("Животное издаёт звук");
    }
}

package com.pythonlib.pets;

import com.pythonlib.animals.Animal;

public class Dog extends Animal {
    public void bark() {
        // Доступ к protected членам родителя
        System.out.println("Я — " + species);  // Работает!
        makeSound();  // Работает!
    }

    public void tryDirectAccess() {
        Animal animal = new Animal();
        // animal.species = "Птица";  // Ошибка! Не через наследование
        // animal.makeSound();  // Ошибка!
    }
}

Важный нюанс: protected доступ через ссылку на объект родителя возможен только если вы находитесь в том же пакете. Если вы в другом пакете — только через this или super в классе-наследнике.

Когда использовать: когда вы создаёте библиотеку или фреймворк и хотите, чтобы наследники могли переопределять или использовать определённые методы, но при этом не хотите открывать их всем.

Public: «Вход без ограничений»

Модификатор public — полная противоположность private. Поле, метод или класс с этим модификатором доступны из любого места: из любого класса, пакета, проекта.

package com.pythonlib.math;

public class Calculator {
    public static final double PI = 3.14159;  // Доступно всем

    public int add(int a, int b) {
        return a + b;
    }
}

// В любом другом классе:
import com.pythonlib.math.Calculator;

public class Test {
    public static void main(String[] args) {
        Calculator calc = new Calculator();
        System.out.println(calc.add(5, 3));  // 8
        System.out.println(Calculator.PI);   // 3.14159
    }
}

Когда использовать: для API вашего класса — методов, которые должны вызывать другие разработчики. Помните: всё, что вы делаете public, вы обязуетесь поддерживать в будущем.

Сравнительная таблица модификаторов доступа

Чтобы наглядно увидеть разницу между public, protected, package-private и private в Java, вот удобная таблица:

Блоги

Рекомендаций по книгам

Модификатор Внутри класса Внутри пакета Наследник (другой пакет) Любой класс
private ✅ ❌ ❌ ❌