了解java protected modifier

时间:2013-09-02 12:13:59

标签: java visibility protected access-modifiers

我在package1中有一个名为A的类,在package2中有一个名为C的类。 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”不可见。这似乎与oracle文档中给出的“protected”关键字的定义冲突。

  

protected修饰符指定只能在自己的包中访问该成员(与package-private一样),此外,还可以在另一个包中通过其类的子类访问。

这里发生了什么?

6 个答案:

答案 0 :(得分:36)

  

这里发生了什么?

你误解了protected的含义。您可以从A内访问C中声明的受保护成员,但仅限于C的实例或C的子类。有关受保护访问的详细信息,请参阅section 6.6.2 of the JLS。特别是:

  

设C是声明受保护成员的类。只允许在C的子类S的主体内访问。

     

此外,如果Id表示实例字段或实例方法,则:

     
      
  • [...]

  •   
  • 如果访问是通过字段访问表达式E.Id,其中E是主表达式,或者是通过方法调用表达式E.Id(...),其中E是主表达式,那么当且仅当E的类型为S或S的子类时,才允许访问

  •   

(强调我的。)

所以这个代码没问题:

C c = new C();
System.out.println(c.publicInt);
System.out.println(c.protectedInt);

答案 1 :(得分:10)

由于C继承AC可以直接使用protected的{​​{1}}变量,如下所示

A

根据您的代码,您正在创建public class C extends A{ public void go(){ System.out.println(protectedInt); } } 的实例并通过该实例访问A变量 ,这违反了java的规则 - 受保护的变量是在包装外不可见

答案 2 :(得分: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

答案 3 :(得分:1)

无需在Protection2 Class中实例化Protection类。您可以直接调用受保护的变量,而无需实例化Protection类。因为Protection2类扩展了Protection类。所以变量自动由子类继承。

尝试使用以下代码:

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

答案 4 :(得分:1)

在声明受保护成员的同一个包中,允许访问:

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
    }
} 

答案 5 :(得分:1)

受保护表示:

a)通过A对象的引用,该成员可以被同一个包中的所有类访问。

b)对于不同的包,只能在A的子类中说B,并且所使用的引用可以是B实例或B的任何子类。

我们举一个例子:

让A成为某个包中的父类,说com.ex1 设B,C为不同包w.r.t中的类到A com.ex2。此外,B extends AC extends B。 我们将看到如何在B内部使用A的受保护字段(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 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 subclass of B
    }
}

C代码:

public class C extends B {

}

对于受保护的静态

同样的规则适用,但在b)中现在可以通过A的类引用在A的任何子类中访问它。 Reference