首页 文章

了解java的protected修饰符

提问于
浏览
30

我在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 回答

  • 1
    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 .

  • 1

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

    尝试使用以下代码:

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

    这里发生了什么?

    你误解了 protected 的含义 . 您可以从 C 中访问 A 中声明的受保护成员,但仅适用于 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

    由于 C 是继承 AC 可以直接使用 protectedprotected 变量,如下所示

    public class C extends A{
    
        public void go(){
    
           System.out.println(protectedInt);
    
        }
    }
    

    根据您的代码,您正在创建 A 的实例并通过该实例访问 protected 变量,这违反了java的规则 - A protected variable is not visible outside the package

  • 2

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

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

    Protected 表示:

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

    对于 protected Static

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

相关问题