41

我在 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 修饰符指定该成员只能在其自己的包中访问(与 package-private 一样),此外,它的类在另一个包中的子类也可以访问。

这里发生了什么?

4

6 回答 6

41

这里发生了什么?

你误解了 的意思protectedA您可以从内部访问在 中声明的受保护成员C,但仅限于 的实例C或子类C。有关受保护访问的详细信息,请参阅JLS 的第 6.6.2 节。尤其是:

令 C 为声明受保护成员的类。只有在 C 的子类 S 的主体内才允许访问。

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

  • [...]

  • 如果通过字段访问表达式 E.Id(其中 E 是 Primary 表达式)或通过方法调用表达式 E.Id(. . .)(其中 E 是 Primary 表达式)进行访问,则当且仅如果 E 的类型是 S 或 S 的子类

(强调我的。)

所以这段代码会很好:

C c = new C();
System.out.println(c.publicInt);
System.out.println(c.protectedInt);
于 2013-09-02T12:17:49.403 回答
10

既然C是继承AC可以直接使用如下的protected变量A

public class C extends A{

    public void go(){

       System.out.println(protectedInt);

    }
}

根据您的代码,您正在创建一个实例并通过该实例A访问protected变量,这违反了 java 的规则 -受保护的变量在包外不可见

于 2013-09-02T12:18:06.433 回答
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你试图访问根据java标准是非法的A的受保护成员时

相反,您可以this.protectedInt直接执行。

于 2013-09-02T12:20:28.837 回答
2

受保护的手段:

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

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

举个例子:

假设 A 是某个包中的父类,com.ex1 假设 B,C 是与 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 的任何子类中访问。参考

于 2018-04-05T22:06:02.977 回答
1

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

试试下面的代码:

public class Protection2 extends Protection{
Protection2()
{System.out.println("n_pro = " +n_pro);
}}
于 2014-12-17T05:45:56.213 回答
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
    }
} 
于 2017-10-16T20:19:15.807 回答