Подтвердить что ты не робот

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

У меня есть класс под названием A в пакете 1 и еще один класс C в пакете2. Класс 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.

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

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

4b9b3361

Ответ 1

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

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

Пусть C - класс, в котором объявлен защищенный член. Доступ разрешен только внутри тела подкласса S из 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

 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 напрямую.

Ответ 4

Не нужно создавать класс защиты внутри класса Protection2. Вы можете напрямую вызвать защищенную переменную без создания экземпляра класса защиты. Поскольку класс Protection2 расширяет класс защиты. Таким образом, переменная автоматически унаследована подклассом.

Попробуйте использовать код ниже:

public class Protection2 extends Protection{
Protection2()
{System.out.println("n_pro = " +n_pro);
}}

Ответ 5

В том же пакете, где объявлен защищенный член, разрешен доступ:

package package1;

public class C extends A{
    public void go(){
        A a = new A();
        System.out.println(a.protectedInt);  // got printed 
        C c = new C();
        System.out.println(c.protectedInt);  // got printed as well
    }
}

Вне пакета, в котором объявлен защищенный член, доступ разрешен тогда и только тогда, когда по коду, ответственному за реализацию этого объекта. В этом случае C отвечает за реализацию этого объекта, поэтому он может получить доступ к защищенному.

package package2;

public class C extends A{
    public void go(){
        A a = new A();
        System.out.println(a.protectedInt);  // compiler complains  
        C c = new C();
        System.out.println(c.protectedInt);  // got printed
    }
}