Я использую этот код для извлечения файла RAR, защищенного паролем. Я использую функцию std :: system ()
для вызова команды RAR. Если я использую пароль
в функции std :: system ()
, он работает. Но поскольку пытается передать пароль в качестве параметра, этого не происходит. Например, если в этом коде я использую пароль pwd
, он дает следующую ошибку:
«pwd не распознается как внутренняя или внешняя команда, public class ProtectedClass { protected void foo () { System.out.println ("фу"); } }
пакет2
:ExtendsprotectedClass.java
пакет org.test.package2; import org.test.package1.ProtectedClass; открытый класс ExtendsprotectedClass extends ProtectedClass { public void boo () { foo (); // Это работает, // поскольку защищенный метод виден через наследование } public static void main (String [] args) { ExtendsprotectedClass epc = new ExtendsprotectedClass (); epc.foo (); // Почему это работает? // Поскольку доступ к нему осуществляется через ссылку, // foo () не должно быть видно, верно? } }
пакет2
:UsesExtendedClass.java
пакет org.test.package2; открытый класс UsesExtendedClass { public static void main (String [] args) { ExtendsprotectedClass epc = new ExtendsprotectedClass (); epc.foo (); // Ошибка компиляции: // Метод foo () из типа ProtectedClass // не видно } }
Подразумевается, что метод
boo ()
вExtendsprotectedClass
может обращаться кfoo ()
, поскольку доступ к защищенным членам можно получить только посредством наследования.] Мой вопрос: почему метод
foo ()
работает нормально при доступе по ссылке в методеmain ()
изExtendsprotectedClass
, но будет не работают при доступе через ссылкуepc
вUsesExtendedClass
?
Код в пределах Классу ExtendsprotectedClass
разрешен доступ к защищенным членам класса ProtectedClass
через ссылку типа ExtendsprotectedClass
. Из раздела JLS 6.6.2 :
Доступ к защищенному члену или конструктору объекта может быть получен извне пакета, в котором он объявлен, только кодом, который отвечает за реализацию этого объекта.
и
Пусть C будет классом, в котором объявлен защищенный член m. Доступ разрешен только в теле подкласса S класса C. Кроме того, если Id обозначает поле экземпляра или метод экземпляра, то:
- Если доступ осуществляется по квалифицированному имени Q.Id, где Q - это ExpressionName, тогда доступ разрешен тогда и только тогда, когда тип выражения Q - S или подкласс S. [...]
UsesExtendedClass
не отвечает за реализацию ExtendsprotectedClass
, следовательно, последний вызов не выполняется.
РЕДАКТИРОВАТЬ: Причина в том, что защищенный
доступ предназначен для того, чтобы помочь подклассам реализовать нужную им функциональность, предоставляя больше доступа к внутренним компонентам суперкласса, чем обычно. Если бы это было доступно для всего кода, это было бы довольно близко к тому, чтобы сделать метод общедоступным. Обычно подклассам доверяют, чтобы они не нарушили инкапсуляцию; им дается больше возможностей в объектах их собственного типа. Общедоступный API не должен раскрывать эти детали, но защищенный API может только с целью предоставления подклассам больше возможностей.
Он работает в первом случае, потому что он вызывается из того же класса, даже если доступ к методу осуществляется через ссылку. Вы даже можете вызвать частный
метод ExtendsprotectedClass
через ссылку в том же основном методе.