2009-01-16 13 views
12

La palabra clave protected otorga acceso a clases en el mismo paquete y subclases (http://java.sun.com/docs/books/tutorial/java/javaOO/accesscontrol.html).¿Cómo se protegen los métodos protegidos de java.lang.Object de las subclases?

Ahora, cada clase tiene java.lang.Object como superclase (http://java.sun.com/j2se/1.5.0/docs/api/java/lang/Object.html).

Por lo tanto, concluyo que cada clase puede acceder a los métodos de java.lang.Object, incluso si son protected.

Tome una mirada en el siguiente ejemplo:

 
public class Testclass { 
    public Object getOne() throws CloneNotSupportedException { 
    return this.clone(); 
    } 
    public Object getTwo() throws CloneNotSupportedException { 
    return ((Object) this).clone(); 
    } 
} 

Mientras getOne() compila bien, getTwo() da

 
Testclass.java:6: clone() has protected access in java.lang.Object 
     return ((Object) this).clone(); 

que ni entender por qué getTwo() no recopila ni lo que es la diferencia (en relación con el acceso de java.lang.Object s miembros) con getOne().

+0

difícil de creer que tenía exactamente la misma confusión cuando miraba a '' Clonable' y Object.clone() '- gracias. – wulfgarpro

Respuesta

16

Solo puede acceder a miembros protegidos de un tipo en un paquete diferente si el tipo de tiempo de compilación de la expresión a la que hace referencia es su propia clase o una subclase. (Donde "tu" clase es la clase que contiene el código.) Tu propia clase tiene que ser una subclase del tipo que originalmente también declara el método.

Aquí hay un ejemplo; asumir que es Base en un paquete diferente a todas las otras clases:

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 {} 

En otras palabras, se le permite tener acceso a los miembros protegidos de "objetos que son como tú".

Los detalles están en section 6.6.2 of the Java Language Specification:

Un protected miembro o constructor de un objeto se puede acceder desde fuera el paquete en el que se declara únicamente por el código que se encarga de la aplicación de esa objeto.

6.6.2.1 El acceso a un miembro protegido

Deje C sea la clase en la que un miembro de protegida m se declara. El acceso está permitido solo dentro del cuerpo de una subclase S de C. Además, si Id denota un campo de instancia o método de instancia , entonces: Si el acceso es por un nombre calificado Q.Id, donde Q es un ExpressionName, entonces el acceso está permitido si y sólo si el tipo de la expresión Q es S o una subclase de S. Si el acceso es por un acceso de campo expresión E.Id, donde E es una expresión primaria , o por una llamada a un método expresión E.Id (...), donde E es una expresión primaria , entonces el acceso está permitido si y sólo si el tipo de e es S o una subclase de S.

+3

Tenga en cuenta que las clases pueden acceder a miembros protegidos de _any_ clase en el mismo paquete. –

+0

Usted tiene un error tipográfico:

 public class Child extends Base {} { […] } 

+0

Vaya, gracias tanto - arreglarán. –

5

Cuando dice "((Object) this).clone()", accede a su propio objeto a través de su objeto de superclase. Usted realizó una conversión de ampliación a un Objeto. El código intenta llamar a clon en Object.

Pero, como habrás notado, clonar es un método protegido, lo que significa que solo si tu objeto estaba en el mismo paquete de java.lang podría acceder al método de clonación del OBJETO.

Cuando dice this.clone, su clase extendió Object y, por lo tanto, tuvo acceso para sobrescribir o usar clon directamente a través del modificador de clase protegida debido a la herencia. Pero eso no cambia la implementación del Objeto.

Al decir ((Object) yourObject), obtienes algo a lo que solo se puede acceder a través de la clase Object. Solo se pueden acceder a los métodos públicos de la clase Object fuera del paquete java.lang, de modo que se obtiene la excepción en tiempo de compilación, porque el compilador lo sabe.

Al decir this.clone(), está invocando el método de clonación de su objeto heredado a través de Object, y ahora se puede invocar porque se convierte en una parte de su subclase personalizada.

+0

Estás confuso protegido con paquete protegido. –

+0

Yo no lo creo: "Cuando dice this.clone, la clase de objeto extendido y por lo tanto tenía acceso a anular o utilizar clon directamente a través del modificador de clase protegida debido a la herencia" –

+0

me nitpicking con esta declaración: "Pero, como usted ha señalado, el clon es un método protegido, lo que significa que sólo si el objeto estaba en el mismo paquete de java.lang ¿sería capaz de acceder método clone del objeto ". A primera vista, eso suena mal. Pero déjame reconsiderar por un momento ... –

1

La diferencia es cómo está accediendo a Object.clone(). clon solo es accesible cuando se accede a través de una subclase o clase en el mismo paquete. En el ejemplo getOne(), está claling this.clone(). Esto claramente satisface el acceso desde dentro de una subclase.

En getTwo() aunque está en proceso Object.clone() y no TestClass.clone(). Para que esto funcione, debe tener acceso a nivel de paquete a Object que no tiene y, por lo tanto, el error.

Cuestiones relacionadas