如何保护java.lang.Object的受保护方法不受子类的影响?

关键字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 )。

因此,我得出结论,即使protected ,每个类都可以访问java.lang.Object的方法。

看一下下面的例子:

公共类Testclass {
   public Object getOne()抛出CloneNotSupportedException {
     return this.clone();
   }
   public Object getTwo()抛出CloneNotSupportedException {
     return((Object)this).clone();
   }
 }

虽然getOne()编译得很好,但getTwo()给出了

 Testclass.java:6:clone()在java.lang.Object中具有受保护的访问权限
         return((Object)this).clone();

我既不理解为什么getTwo()没有编译,也没有理解与getTwo()什么区别(关于java.lang.Object成员的访问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的类。 只允许在C的子类S的主体内访问。 此外,如果Id表示实例字段或实例方法,则:如果访问是通过限定名称Q.Id ,其中QExpressionName ,则当且仅当表达式Q的类型为S时才允许访问或S的子类。 如果访问是通过字段访问表达式E.Id ,其中E表达式,或者是通过方法调用表达式E.Id(…) ,其中E表达式,那么只允许访问如果E的类型是SS的子类。

当你说“ ((Object) this).clone() ”时,你通过它的超类Object访问了你自己的对象。 您执行了对象的扩展转换。 然后代码尝试在Object上调用clone。

但是,正如您所指出的,clone是一种受保护的方法,这意味着只有当您的对象位于java.lang的同一个包中时,它才能访问OBJECT的clone方法。

当你说this.clone时,你的类扩展了Object,因此可以通过受保护的类修饰符直接覆盖或使用克隆,因为inheritance。 但这并没有改变Object的实现。

通过说((Object)yourObject),你得到的东西只能通过Object类访问。 只有java类的公共方法可以在java.lang包中访问,所以你得到编译时exception,因为编译器知道这一点。

通过说this.clone(),您正在调用通过Objectinheritance而获得的对象的clone方法,现在可以调用它,因为它成为自定义子类的一部分。

不同之处在于您访问Object.clone()的方式。 只有通过同一个包中的子类或类访问时,才能访问clone。 在getOne()示例中,您正在使用this.clone()。 这显然满足子类内的访问。

在getTwo()中虽然您正在访问Object.clone()而不是 TestClass.clone()。 为了使其工作,您必须具有对象的包级访问权限,而不是错误。