该关键字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
s成员的访问)getOne()
.
如果您引用它的表达式的编译时类型是您自己的类或子类,则只能访问其他包中的类型的受保护成员.(其中"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 {}
换句话说,它允许您访问"像您一样的对象"的受保护成员.
详细信息在Java语言规范的6.6.2节中:
甲
protected
对象的成员或构造可以从它仅由代码中声明的封装,它负责该对象的执行外部访问.6.6.2.1访问受保护的成员
设C是声明受保护成员m的类.访问仅在一个子类的主体允许小号的Ç.此外,如果Id表示实例字段或实例方法,则:如果访问是通过限定名称Q.Id,其中Q是 ExpressionName,则当且仅当表达式Q的类型为S时才允许访问或S的子类 .如果访问是通过字段访问表达式E.Id,其中E是主要的 表达,或通过一个方法调用表达式(.)E.Id,其中Ë是一个 主要表达,则接入是允许的,当且仅当的类型ë 是小号或的一个子类小号.
当你说" ((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方法,现在可以调用它,因为它成为你的自定义子类的一部分.