Модификатор доступа protected позволяет членам класса быть видимыми внутри того же пакета (package) и во всех подклассах (subclasses), даже если они находятся в других пакетах.
Различия c другими модификаторами:
private — доступ только в пределах текущего классаprotected — доступен внутри текущего пакета и в наследниках вне пакетаpublic — доступен вездеПример:
package com.example.base; public class Parent { protected void sayHello() { System.out.println("Hello from parent"); } } package com.example.child; import com.example.base.Parent; public class Child extends Parent { public void tryHello() { sayHello(); // Доступ есть! } } public class NotChild { public void fail(Parent p) { // p.sayHello(); // Ошибка: нет доступа } }
Может ли внешний класс (не являющийся наследником) получить доступ к
protected-методу из другого пакета, имея объект этого класса?
Ответ: Нет, доступ к protected-методу из другого пакета разрешён только классам-наследникам, и только через this или через ссылку на объект-наследник, а не на родителя.
Parent p = new Child(); p.sayHello(); // Ошибка! ((Child) p).sayHello(); // Успех (если обращается внутри Child)
История
В большом модульном проекте разработчик поместил важные бизнес-методы в
protected-секцию, полагая, что они недоступны вне пакета. Другие разработчики случайно использовали эти методы в тестах в том же пакете, и из-за последующего перемещения классов возникли неожиданные ошибки доступа.
История
В проекте микросервисов метод с protected-доступом пытались вызывать по ссылке на тип родителя в другом пакете — вызов не работал. Это вызвало сбой в части механизмов расширения системы, потому что полагались на некорректное понимание области видимости.
История
В open-source библиотеке невнимательно использовали protected-поля, которые оказались доступны слишком широкому кругу классов, что позволило случайно повредить внутреннее состояние объекта, вызвав проблемы в сторонних приложениях.