了解java的protected修饰符

mah*_*007 35 java visibility protected access-modifiers

我在package1中有一个名为A的类,在package2中有一个名为C的类.C类扩展了A类.

A有一个实例变量,声明如下:

protected int protectedInt = 1;
Run Code Online (Sandbox Code Playgroud)

这是A类的代码

package package1;

public class A {

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

}
Run Code Online (Sandbox Code Playgroud)

这是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);

    }
}
Run Code Online (Sandbox Code Playgroud)

Eclipse强调了C.go()中的最后一行,并说"A.protectedInt"不可见.这似乎与oracle文档中给出的"protected"关键字的定义冲突.

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

这里发生了什么?

Jon*_*eet 37

这里发生了什么?

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

设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);
Run Code Online (Sandbox Code Playgroud)

  • @ mahela007:不是没有`保护',不是 - 如果它是默认(包)可见性或'私人',它将不可见. (2认同)
  • @ mahela007:但是`E`在这里是`A`,而`S`是`C`.虽然`C`是`A`的子类,但`A`*不是*C`的子类. (2认同)

san*_*hat 10

由于C是继承A,C可以直接使用下面的protected变量A

public class C extends A{

    public void go(){

       System.out.println(protectedInt);

    }
}
Run Code Online (Sandbox Code Playgroud)

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


Bre*_*min 6

受保护的意思是:

\n

a) 同一包中的所有类都可以通过 A object\xe2\x80\x99s 引用访问该成员。

\n

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

\n

让我们举个例子:

\n

令 A 成为某个包中的父类,例如com.ex1

\n

假设 B 和 C 是与 A 相关的不同包中的类com.ex2。还有,B extends AC extends B

\n

我们将看到如何在 B(A 的子类)中使用 A 的受保护字段。

\n

A的代码:

\n
public class A {\n    protected int a = 10;\n}\n
Run Code Online (Sandbox Code Playgroud)\n

B的代码:

\n
public class B extends A {\n\n\n    public void printUsingInheritance() {\n        // Using this\n        System.out.println(this.a);\n    }\n\n    public void printUsingInstantiation() {\n        // Using instance of B\n        B b = new B();\n        System.out.println(b.a);\n\n        // Using instance of C as C is a subclass of B\n        C c = new C();\n        System.out.println(c.a);\n\n        A a = new A();\n        System.out.println(a.a); // Compilation error as A is not a subclass of B\n    }\n}\n
Run Code Online (Sandbox Code Playgroud)\n

C的代码:

\n
public class C extends B {\n\n}\n
Run Code Online (Sandbox Code Playgroud)\n

对于受保护的静态

\n

相同的规则适用,除了 b) 中现在可以通过 A 的类引用在 A 的任何子类中访问它。参考

\n