关键字protected
授予对同一包和子类(http://java.sun.com/docs/books/tutorial/java/javaOO/accesscontrol.html)中的类的访问权限。
现在,每个班级都有java.lang.Object
作为超类(http://java.sun.com/j2se/1.5.0/docs/api/java/lang/Object.html)。
因此,我得出结论,每个班级都可以访问java.lang.Object
的方法,即使它们是protected
。
看看下面的例子:
public class Testclass { public Object getOne() throws CloneNotSupportedException { return this.clone(); } public Object getTwo() throws CloneNotSupportedException { return ((Object) this).clone(); } }
虽然getOne()
编译得很好,getTwo()
会给出
Testclass.java:6: clone() has protected access in java.lang.Object return ((Object) this).clone();
我既不理解getTwo()
无法编译的原因,也不理解java.lang.Object
成员与getOne()
成员的访问权限有何不同。
答案 0 :(得分:16)
如果您引用它的表达式的编译时类型是您自己的类或子类,则只能访问其他包中的类型的受保护成员。 (其中“your”类是包含代码的类。)您自己的类必须是最初声明该方法的类型的子类。
这是一个例子;假设Base
与所有其他类位于不同的包中:
package first;
public class Base
{
protected void Foo() {}
}
// Yes, each class is really in its own file normally - but treat
// all the classes below as being in package "second"
package second;
public class Child extends Base
{
public void OtherMethod(Object x)
{
((Base) x).Foo(); // Invalid: Base is not Child or subclass
((Child) x).Foo(); // Valid: Child is Child
((GrandChild) x).Foo(); // Valid: GrandChild is subclass of Child
((OtherChild) x).Foo(); // Invalid: OtherChild is not Child or subclass
}
}
public class GrandChild extends Child {}
public class OtherChild extends Base {}
换句话说,它允许您访问“与您类似的对象”的受保护成员。
详细信息位于section 6.6.2 of the Java Language Specification:
protected
成员或构造函数 可以从外部访问对象 声明它的包 只有负责的代码 该对象的实现。6.6.2.1访问受保护的成员
让 C 成为a的类 声明受保护的成员 m 。访问 只允许在一个体内 C 的子类 S 。另外,如果Id 表示实例字段或实例 方法,然后:如果访问是由a 限定名称 Q.Id ,其中 Q 是 ExpressionName ,然后是访问权限 当且仅当类型允许时允许 表达式 Q 是 S 或其子类 取值。如果访问是通过字段访问 表达式 E.Id ,其中 E 是主要 表达式,或通过方法调用 表达式 E.Id(...),其中 E 是a 主要表达式,然后访问权限 当且仅当 E 的类型允许时 是 S 或 S 的子类。
答案 1 :(得分:5)
当您说“((Object) this).clone()
”时,您通过其超类Object访问了自己的对象。您执行了对象的扩展转换。然后代码尝试在Object上调用clone。
但是,正如您所注意到的,clone是一种受保护的方法,这意味着只有当您的对象位于java.lang的同一个包中时,它才能访问OBJECT的clone方法。
当你说this.clone时,你的类扩展了Object,因此可以通过受保护的类修饰符直接覆盖或使用克隆,因为继承。但这并没有改变Object的实现。
通过说((Object)yourObject),你得到的东西只能通过Object类访问。只有java类的公共方法可以在包java.lang中访问,因此你得到编译时异常,因为编译器知道这一点。
通过说this.clone(),你正在调用你通过Object继承的对象的clone方法,现在可以调用它,因为它成为你的自定义子类的一部分。
答案 2 :(得分:1)
不同之处在于您访问Object.clone()的方式。只有通过同一个包中的子类或类访问时,才能访问clone。在getOne()示例中,您正在使用this.clone()。这显然满足子类内的访问。
在getTwo()中虽然您正在访问Object.clone()和而不是 TestClass.clone()。为了使其工作,您必须具有对象的包级别访问权限,而不是错误。