Вопрос-ответ

Understanding Java's protected modifier

Понимание защищенного модификатора Java

У меня есть класс с именем A в package1 и другой класс с именем C в package2. Класс C расширяет класс A.

A имеет переменную экземпляра, которая объявляется следующим образом:

protected int protectedInt = 1;

Вот код для класса A

package package1;

public class A {

public int publicInt = 1;
private int privateInt = 1;
int defaultInt = 1;
protected int protectedInt = 1;

}

А вот и код для класса C:

package package2;
import package1.A;

public class C extends A{

public void go(){
//remember the import statement
A a = new A();
System.out.println(a.publicInt);
System.out.println(a.protectedInt);

}
}

Eclipse подчеркивает последнюю строку в C.go() и говорит "A.protectedInt" не отображается. Похоже, что это противоречит определению ключевого слова "protected", учитывая, что в документации Oracle говорится:


Защищенный модификатор указывает, что к члену можно получить доступ только в его собственном пакете (как в случае с package-private) и, кроме того, подклассом его класса в другом пакете.


Что здесь происходит?

Переведено автоматически
Ответ 1

Что здесь происходит?


Вы неправильно поняли значение protected. Вы можете получить доступ к защищенным элементам, объявленным в A изнутри C, но только для экземпляров C или подклассов C. Смотрите раздел 6.6.2 JLS для получения подробной информации о защищенном доступе. В частности:


Пусть C будет классом, в котором объявлен защищенный член. Доступ разрешен только в теле подкласса-Ов C.


Кроме того, если Id обозначает поле экземпляра или метод экземпляра, то:



  • [...]



  • Осуществляется ли доступ с помощью выражения доступа к полю E.Id, где E - первичное выражение, или с помощью выражения вызова метода E.Id(. . .), где E является основным выражением, тогда доступ разрешен тогда и только тогда, когда тип E равен S или подклассу S.




(Выделено мной.)

Итак, этот код был бы прекрасен:

C c = new C();
System.out.println(c.publicInt);
System.out.println(c.protectedInt);
Ответ 2

Поскольку C наследуется A, C можно напрямую использовать protected переменную A, как показано ниже

public class C extends A{

public void go(){

System.out.println(protectedInt);

}
}

Согласно вашему коду, вы создаете экземпляр A и получаете доступ к protected переменной через этот экземпляр, что нарушает правило java - защищенная переменная не видна за пределами пакета

Ответ 3

Защищенный означает:

a) Этот элемент будет доступен для всех классов в одном пакете через ссылку на объект.

b) Для разных пакетов он будет доступен только внутри подклассов A, скажем B, и используемой ссылкой может быть экземпляр B или любого подкласса B.

Давайте рассмотрим пример:

Пусть A будет родительским классом в некотором пакете, скажем, com.ex1.

Пусть B и C будут классами в разных пакетах по отношению к A, скажем, com.ex2. Также, B extends A и C extends B.

Мы увидим, как мы можем использовать защищенные поля A внутри B (подкласса A).

Код A:

public class A {
protected int a = 10;
}

Код B:

public class B extends A {


public void printUsingInheritance() {
// Using this
System.out.println(this.a);
}

public void printUsingInstantiation() {
// Using instance of B
B b = new B();
System.out.println(b.a);

// Using instance of C as C is a subclass of B
C c = new C();
System.out.println(c.a);

A a = new A();
System.out.println(a.a); // Compilation error as A is not a subclass of B
}
}

Код C:

public class C extends B {

}

Для защищенной статики:

Применяются те же правила, за исключением того, что в b) теперь он доступен в любом подклассе A по ссылке на класс A. Ссылка

Ответ 4
 public void go(){
//remember the import statement
A a = new A();
System.out.println(a.publicInt);
System.out.println(a.protectedInt);

}

Когда вы делаете A a = new A(); и a.protectedInt пытаетесь получить доступ к защищенному члену A, что незаконно в соответствии со стандартами Java

Вместо этого вы можете сделать this.protectedInt напрямую.

java