了解java';s保护修饰语
我在package1中有一个名为a的类,在package2中有另一个名为C的类。C类扩展了A类 A有一个实例变量,声明如下:了解java';s保护修饰语,java,visibility,protected,access-modifiers,Java,Visibility,Protected,Access Modifiers,我在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 prote
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修饰符指定成员只能在其自己的包内访问(与包private一样),此外,还可以由另一个包中其类的子类访问
这是怎么回事
这是怎么回事
您误解了受保护的的含义。您可以从C
中访问A
中声明的受保护成员,但只能访问C
的实例或C
的子类。有关受保护访问的详细信息,请参阅。特别是:
设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);
由于C
继承了A
,C
可以直接使用A
的受保护的变量,如下所示
public class C extends A{
public void go(){
System.out.println(protectedInt);
}
}
根据您的代码,您正在创建A
的实例,并通过该实例访问受保护的
变量,这违反了java的规则-受保护的变量在包外不可见
public void go(){
//remember the import statement
A a = new A();
System.out.println(a.publicInt);
System.out.println(a.protectedInt);
}
当您执行A A=newa()时
和a.protectedInt
您试图访问的受保护成员根据java标准是非法的
相反,您可以直接执行这个.protectedInt
。无需在Protection2类中实例化Protection类。您可以直接调用受保护变量,而无需实例化保护类。因为Protection2类扩展了保护类。所以变量自动被子类继承
请尝试以下代码:
public class Protection2 extends Protection{
Protection2()
{System.out.println("n_pro = " +n_pro);
}}
在声明受保护成员的同一包中,允许访问:
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
}
}
受保护表示:
a) 同一包中的所有类都可以通过对象的引用访问此成员
b) 对于不同的包,这将只能在A的子类(比如b)中访问,并且使用的引用可以是b实例的引用,也可以是b的任何子类的引用
让我们举一个例子:
让一个类成为某个包中的父类,比如说com.ex1
假设B,C是不同包w.r.t中的类,比如说com.ex2
。另外,B扩展A
,而C扩展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的任何子类中访问它 如果两个类都在同一个包中,那么原始代码就可以工作。“对象的受保护成员或构造函数只能由负责实现该对象的代码从包外部进行访问。如何才能从“实现对象”的代码中进行访问?”是否在同一对象的包之外?@mahela007:看看您的示例-成员在A
中声明,它与类C
在不同的包中,类C是“实现”类型C
的对象的。在这种情况下,为什么java会有受保护的修饰符?简单地使C扩展A不足以使protectedInt对C可见吗?@mahela007:如果它不受保护
,就不能,不-如果它是默认(包)可见性或私有
,它就不可见。嗯。。。答案中强调的部分说“如果E是S的子类,则允许访问”。。但在我的例子中,C是a的一个子类,我仍然无法访问受保护的变量。@mahela007:但是E
在这里是a
,而S
是C
。尽管C
是a
的子类,a
不是C
的子类。请记住,受保护的方法和变量不仅对子类可见,而且对同一包中的类可见(就像默认对象一样)。所以文档中说“如果且仅当”是错误的。(大家自己试试这个)。