我在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一样),此外,还可以在另一个包中通过其类的子类访问。
这里发生了什么?
答案 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
继承A
,C
可以直接使用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 A
和C 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