В чем разница между модификаторами доступа package-private (default) и protected в Java?

Ответ

Package-private (default) — модификатор доступа по умолчанию, применяемый, когда модификатор не указан явно. Он разрешает доступ к члену класса только для классов из того же пакета.

Protected — разрешает доступ:

  1. Классам из того же пакета (как package-private).
  2. Подклассам (наследникам), даже если они находятся в других пакетах.

Пример, иллюстрирующий разницу:

// Файл: com/example/Parent.java
package com.example;

public class Parent {
    void packagePrivateMethod() {} // Доступ только в пакете com.example
    protected void protectedMethod() {} // Доступ в пакете com.example + подклассы
}
// Файл: com/other/Child.java
package com.other;
import com.example.Parent;

public class Child extends Parent {
    void test() {
        // packagePrivateMethod(); // ОШИБКА КОМПИЛЯЦИИ: класс в другом пакете
        protectedMethod(); // OK: Child является подклассом Parent
    }
}

Итог: protected расширяет видимость package-private, добавляя доступ для подклассов вне пакета.

Ответ 18+ 🔞

Ну слушай, вот есть у тебя эти модификаторы доступа, как будто уровни секретности в какой-то конторе. Самый скромный из них — это package-private (default). Это когда ты просто нихуя не пишешь перед методом или полем. Как будто говоришь: «Ты, сука, можешь тут шариться, но только в пределах нашего отдела (пакета). На улицу не высовывайся, а то получишь по ебалу от компилятора».

А потом идёт protected. Это уже более хитрая жопа. Он говорит: «Всё, что можно отделу (пакету), можно и тебе. А ещё — если ты мой сынок (подкласс), даже если ты живёшь в другом городе (пакете), то подходи, родной, я тебе тоже доверяю».

Вот смотри, чтобы не было, как у того немого Герасима, который только «Му-му» мог сказать, а объяснить нихуя не мог.

Допустим, есть у нас класс-родитель. Он как тот здоровый мужик в конторе com.example.

package com.example;

public class Parent {
    void packagePrivateMethod() {} // Типа "Му-му". Только для своих в палате номер шесть (пакете).
    protected void protectedMethod() {} // А это уже "Му-му, сынок, подойди". И для палаты, и для наследничков.
}

А теперь появляется его отпрыск, который уехал на заработки в другой район (com.other).

package com.other;
import com.example.Parent;

public class Child extends Parent {
    void test() {
        // packagePrivateMethod(); // ОШИБКА КОМПИЛЯЦИИ! Ёпта, отец тебе из другого района кричит "Му-му!" — ты нихуя не понял, и правильно.
        protectedMethod(); // А вот это — ОК! Потому что ты его кровиночка, наследник. Отец тебе доверяет, даже на расстоянии.
    }
}

Итог, блядь, простой: protected — это как package-private, но с семейной скидкой для детей, даже если они отбились от рук и живут в другом пакете. А default — это суровый мужик, который нихуя не пускает за пределы своего подъезда. Всё, в рот меня чих-пых, теперь понятно?