我有3个A,B,C类:
package com.training.protectedclass.A;
public class A
{
protected int value;
}
package com.training.protectedclass.B;
import com.training.protectedclass.A.A;
public class B extends A
{
public void test()
{
this.value = 10;
A a = new A();
a.value = 12; //Error => The field A.value is not visible
}
}
package com.training.protectedclass.C;
import com.training.protectedclass.B.B;
import com.training.protectedclass.A.A;
public class C extends A
{
public void test()
{
B b = new B();
b.value = 45; //Error => The field A.value is not visible
}
}
当继承的类存在于与基类不同的包中时,它无法访问基类的受保护成员。但是当所有三个类都存在于同一个包中时,上述错误就会消失,并且代码编译时没有错误。
有人能解释一下我在上面的代码中启动的每个错误的原因吗?
谢谢:)
答案 0 :(得分:3)
这是因为Java中的protected
意味着两件事:1)继承的类可以看到它们继承的受保护成员,2)同一个包中的其他类可以看到受保护的成员(即使它们不继承会员)。
因此,在课程B
中,您继承了value
,因此您可以通过this.value
访问它,但由于课程A
位于另一个包中,您无法看到{ {1}}。这是因为当您调用a.value
时,您正在访问另一个包中的类的成员而不是字段a.value
的继承版本。
对于课程value
,您无法访问C
的任何受保护成员,因为您既不从B
继承,也不在与B
相同的包中
答案 1 :(得分:1)
Java Language Specification以这种方式定义受保护的访问修饰符:
对象的受保护成员或构造函数可以从包外部访问,只能通过负责实现该对象的代码来声明它。
当你有this.value = 10;
时,B对象访问它自己的一个成员,这是一个在超类中声明的受保护字段。另一方面,当您有new A().value
时,B对象会尝试访问它未实现的对象的受保护成员。
答案 2 :(得分:1)
http://docs.oracle.com/javase/tutorial/java/javaOO/accesscontrol.html中的文档说明了这一点。
protected修饰符指定只能访问该成员 在它自己的包中(与package-private一样),另外,通过 另一个包中其类的子类。
但问题是,您正在尝试访问与this
不同的对象的受保护成员。检查一下http://bmanolov.free.fr/javaprotection.php
答案 3 :(得分:1)
我认为JLS 6.6.2.1给出了答案:
设C是声明受保护成员的类。访问是 只允许在C的子类S的主体内使用。
此外,如果Id表示实例字段或实例方法,则:
如果访问是通过限定名称Q.Id,其中Q是 ExpressionName,当且仅当类型时才允许访问 表达式Q是S或S的子类。
如果访问是通过字段访问表达式E.Id,其中E是a 主表达式,或方法调用表达式E.Id(...), 其中E是主表达式,如果和,则允许访问 只有当E的类型是S或S的子类时。
您正在访问value
正文中的成员B
。因此,对于应用此子句,S为B
,并且根据最后一段,当您尝试访问某些表达式E的E.value
时,仅当E的类型为B或B的子类。由于类型是A,它不是B的子类,因此该条件失败。