Почему я не могу использовать защищенные конструкторы вне пакета?
Почему я не могу использовать защищенные конструкторы вне пакета для этого фрагмента кода:
package code;
public class Example{
protected Example(){}
...
}
Check.java
package test;
public class Check extends Example {
void m1() {
Example ex=new Example(); //compilation error
}
}
- Почему я получаю ошибку, хотя я расширил класс?
Пожалуйста, объясните
EDIT:
Ошибка компиляции:
The constructor Example() is not visible
Ответы
Ответ 1
Защищенный модификатор используется только в пакете и в подклассах вне пакета. Когда вы создаете объект с помощью Example ex=new Example();
, он по умолчанию вызовет конструктор родительского класса.
В качестве защищенного конструктора родительского класса вы получаете ошибку времени компиляции. Вы должны вызвать защищенный конструктор в соответствии с JSL 6.6.2.2, как показано ниже в примере 2.
package Super;
public class SuperConstructorCall {
protected SuperConstructorCall() {
}
}
package Child;
import Super.SuperConstructorCall;
public class ChildCall extends SuperConstructorCall
{
public static void main(String[] args) {
SuperConstructorCall s = new SuperConstructorCall(); // Compile time error saying SuperConstructorCall() has protected access in SuperConstructorCall
}
}
Пример 2, соответствующий JLS 6.6.2.2:
package Super;
public class SuperConstructorCall {
protected SuperConstructorCall() {
}
}
package Child;
import Super.SuperConstructorCall;
public class ChildCall extends SuperConstructorCall
{
public static void main(String[] args) {
SuperConstructorCall s = new SuperConstructorCall(){}; // This will work as the access is by an anonymous class instance creation expression
}
}
Ответ 2
Обычно protected
означает только доступ к подклассам или классам в одном пакете. Однако вот правила для конструкторов из JLS:
6.6.2.2. Квалифицированный доступ к защищенному конструктору
Пусть C - класс, в котором объявлен защищенный конструктор, и пусть S - самый внутренний класс, в заявлении которого используется защищенный конструктор. Тогда:
Если доступ осуществляется вызовом конструктора суперкласса super (...), или квалифицированный вызов конструктора суперкласса E.super(...), где E является Первичным выражением, тогда доступ разрешен.
Если доступ осуществляется с помощью выражения создания экземпляра анонимного класса новый C (...) {...}, или создание квалифицированного экземпляра анонимного класса выражение E.new C (...) {...}, где E - первичное выражение, тогда доступ разрешен.
Если доступ осуществляется с помощью простого экземпляра создания экземпляра класса new C (...) или выражение для создания экземпляра квалифицированного класса E.new C (...), где E - первичное выражение или ссылка на метод выражение C:: new, где C - тип ClassType, тогда доступ не является разрешенный. К защищенному конструктору можно получить доступ к экземпляру класса (которое не объявляет анонимный класс) или ссылочное выражение метода только из пакета, в котором оно определяется.
В качестве примера это не компилируется
public class Example extends Exception {
void method() {
Exception e = new Exception("Hello", null, false, false);
}
}
но это делает
public class Example extends Exception {
Example() {
super("Hello", null, false, false);
}
}
и это делает
public class Example {
void method() {
Exception e = new Exception("Hello", null, false, false) {};
}
}
Итак, правила понятны, но я не могу сказать, что понимаю причины, лежащие в их основе!
Ответ 3
Фактически вы уже используете защищенный конструктор примера, потому что Check имеет неявный конструктор и неявный вызов конструктора примера:
public Check() {
super();
}