理解java的protected修饰符

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/18573016/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-12 09:07:04  来源:igfitidea点击:

Understanding java's protected modifier

javavisibilityprotectedaccess-modifiers

提问by mahela007

I have a class called A in package1 and another class called C in package2. Class C extends class A.

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

A has an instance variable which is declared like this:

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

protected int protectedInt = 1;

Here is the code for class A

这是A类的代码

package package1;

public class A {

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

}

And here is the code for class C:

这是 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 underlines the last line in C.go() and says "A.protectedInt" is not visible. It seems that this conflicts with the definition of the "protected" keyword, given in the oracle documentation.

Eclipse 在 C.go() 中的最后一行下划线并说“A.protectedInt”不可见。这似乎与 oracle 文档中给出的“protected”关键字的定义相冲突。

The protected modifier specifies that the member can only be accessed within its own package (as with package-private) and, in addition, by a subclass of its class in another package.

protected 修饰符指定该成员只能在它自己的包中访问(如包私有),此外,它的类的子类在另一个包中可以访问。

What's going on here?

这里发生了什么?

采纳答案by Jon Skeet

What's going on here?

这里发生了什么?

You've misunderstood the meaning of protected. You can access the protected members declared in Afrom within C, but only for instances of Cor subclasses of C. See section 6.6.2 of the JLSfor details of protected access. In particular:

你误解了 的意思protected。您可以A从 内部访问 中声明的受保护成员C,但只能访问 的实例C或 的子类C。有关受保护访问的详细信息,请参阅JLS 的第 6.6.2 节。特别是:

Let C be the class in which a protected member is declared. Access is permitted only within the body of a subclass S of C.

In addition, if Id denotes an instance field or instance method, then:

  • [...]

  • If the access is by a field access expression E.Id, where E is a Primary expression, or by a method invocation expression E.Id(. . .), where E is a Primary expression, then the access is permitted if and only if the type of E is S or a subclass of S.

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

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

  • [...]

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

(Emphasis mine.)

(强调我的。)

So thiscode would be fine:

所以这段代码没问题:

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

回答by sanbhat

Since Cis inheriting A, Ccan directly use the protectedvariable of Alike below

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

public class C extends A{

    public void go(){

       System.out.println(protectedInt);

    }
}

As per your code, you are creating an instance of Aand accessing protectedvariable through that instance, which violates java's rule - A protected variable is not visible outside the package

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

回答by Abhishek Singh

 public void go(){
        //remember the import statement
        A a = new A();
        System.out.println(a.publicInt);
        System.out.println(a.protectedInt);

    }

When you are doing A a = new A();and a.protectedIntyou trying to access protected member of A which is illegal according to java standards

当你正在做的A a = new A();a.protectedInt你试图A的访问受保护的成员根据Java标准这是违法的

Instead you can do this.protectedIntdirectly.

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

回答by Sugumar

No need to instantiate Protection class inside Protection2 Class. You can directly call the protected variable without instantiating the Protection class. Because Protection2 class extends Protection class. So variable automatically inherited by subclass.

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

Try with below code:

尝试使用以下代码:

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

回答by Ethan

Within the same package where the protected member is declared, access is permitted:

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

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

Outside the package where the protected member is declared, access is permitted if and only if by code that is responsible for the implementation of that object. In this case, C is responsible for the implementation of that object, so it could access the protected.

在声明受保护成员的包之外,当且仅当负责实现该对象的代码允许访问。在这种情况下,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
    }
} 

回答by Number945

Protectedmeans :

受保护的意思是:

a)This member will be accessible to all classes in same package through A object's reference.

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

b) For different package, this will be accessible only inside Subclasses of A say B and the reference used can be of B instance or of any subclass of B.

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

Let's take an example:

让我们举个例子:

Let A be parent class in some package say com.ex1Let B ,C be classes in different package w.r.t to A say com.ex2. Also, B extends Aand C extends B. We will see how we can use protected field of A inside B (a subclass of A)

让 A 成为某个包中的父类,比如说com.ex1让 B,C 成为与 A 不同的包中的类com.ex2。还有,B extends AC extends B。我们将看到如何在 B(A 的子类)中使用 A 的受保护字段

A's code:

A的代码:

public class A {
    protected int a = 10;
}

B's code:

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's code:

C的代码:

public class C extends B {

}

For protected Static:

对于受保护的静态

Same rules apply except that in b) now it is accessible in any subclass of A by A's class reference. Reference

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