diferencia entre los modificadores de acceso protegido y paquete-privado en Java? [duplicar]


Esta pregunta ya tiene una respuesta aquí:

He visto varios artículos sobre las diferencias entre los modificadores protegidos y los privados de paquetes. Una cosa que encontré contradictoria entre estos dos mensajes

  1. No es ¿el acceso del miembro" paquete privado " es sinónimo del acceso predeterminado (sin modificador)?

    En esto la respuesta aceptada dice que

    El modificador protected especifica que el miembro solo puede ser accedido dentro de su propio paquete (como con package-private) y, además, por una subclase de su clase en otro paquete.

  2. ¿Por qué el modificador protegido se comporta de manera diferente aquí en la subclase Java?

    En esto la respuesta aceptada dice que

    Para satisfacer el nivel de acceso protegido se deben cumplir dos condiciones:

    • Las clases deben estar en el mismo paquete.
    • Debe haber una relación de herencia.

¿No son contradictorios? desde mi comprensión de otros artículos, el primer post da la respuesta correcta que protected = = package-private + subclase en otro paquete.

Si esta instrucción es correcta, entonces por qué este código falla con el siguiente mensaje de error en mi subclase Cat en la línea 17

The method testInstanceMethod() from the type Animal is not visible 

Mi código para super y subclase están abajo.

package inheritance;

public class Animal {

    public static void testClassMethod() {
        System.out.println("The class" + " method in Animal.");
    }
    protected void testInstanceMethod() {
        System.out.println("The instance " + " method in Animal.");
    }
}

package testpackage;

import inheritance.Animal;

public class Cat extends Animal{
        public static void testClassMethod() {
            System.out.println("The class method" + " in Cat.");
        }
        public void testInstanceMethod() {
            System.out.println("The instance method" + " in Cat.");
        }

        public static void main(String[] args) {
            Cat myCat = new Cat();
            Animal myAnimal = myCat;
            myAnimal.testClassMethod();
            myAnimal.testInstanceMethod();
        }
    }

Por favor, aclare por qué el código anterior falla. Eso sería muy útil. Gracias

Author: Community, 2013-08-28

3 answers

La primera respuesta es básicamente correcta - protected los miembros pueden ser accedidos por

  • clases del mismo paquete
  • subclases de la clase declarante de otros paquetes

Sin Embargo, hay un pequeño truco:

6.6.2 Detalles sobre el Acceso protegido

Se puede acceder a un miembro protegido o constructor de un objeto desde fuera del paquete en el que se declara solo por código que es responsable de la implementación de ese objeto.

Significa que la subclase de otro paquete no puede acceder a protected miembros de instancias arbitrarias de sus superclases, solo pueden acceder a ellas en instancias de su propio tipo (donde type es un tipo de expresión en tiempo de compilación, ya que es una comprobación en tiempo de compilación).

Por ejemplo (suponiendo que este código está en Cat):

Dog dog = new Dog();
Animal cat = new Cat();

dog.testInstanceMethod(); // Not allowed, because Cat should not be able to access protected members of Dog
cat.testInstanceMethod(); // Not allowed, because compiler doesn't know that runtime type of cat is Cat

((Cat) cat).testInstanceMethod(); // Allowed

Tiene sentido, porque el acceso de protected miembros de Dog por Cat puede romper invariantes de Dog, mientras que Cat puede acceder a sus propios protected miembros de forma segura, porque sabe cómo asegurar sus propios invariantes.

Disposiciones de aplicación:

6.6.2.1 Acceso a un Miembro protegido

Sea C la clase en la que se declara un miembro protegido m. El acceso solo está permitido 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 es permitido si y solo si el tipo de la expresión Q es S o una subclase de S.
  • Si el acceso es por una expresión de acceso de campo E.Id, donde E es una expresión primaria, o por una expresión de invocación de método E.Id(. . .), donde E es una expresión Primaria, entonces el acceso está permitido si y solo si el tipo de E es S o una subclase de S.

6.6.2.2 Acceso cualificado a un Constructor protegido

Sea C el clase en la que se declara un constructor protegido y sea S la clase más interna en cuya declaración se produce el uso del constructor protegido. Entonces:

  • Si el acceso es por una invocación del constructor superclass super(. . .) o por un constructor de superclase calificado invocación de la forma E. super(. . .), donde E es una expresión Primaria, entonces se permite el acceso.
  • Si el acceso es por una expresión de creación de instancia de clase anónima de la forma new C(. . .){...} o por una expresión de creación de instancia de clase calificada de la forma E. new C(. . .){...}, donde E es una expresión Primaria, entonces el acceso está permitido.
  • De lo contrario, si el acceso es por una simple expresión de creación de instancia de clase de la forma new C(. . .) o por una expresión de creación de instancia de clase calificada de la forma E. new C(. . .), donde E es una expresión Primaria, entonces el acceso no está permitido. Se puede acceder a un constructor protegido mediante una expresión de creación de instancia de clase (que no declara una clase anónima) solo desde dentro del paquete en el que está definida.

Véase también:

 24
Author: axtavt,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-08-28 18:24:22

En acceso protegido se accede a los miembros en el mismo paquete y para el miembro de clase heredado en otro paquete también se puede acceder.

En package access se puede acceder a los miembros de las clases del mismo paquete. No se puede acceder a los miembros de la clase en otros paquetes en acceso a paquetes.

 2
Author: Muhammad kazmi,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-01-10 18:45:48

Ha creado una instancia Cat y la ha enviado a su tipo superclase, es decir, Tipo Animal. Según el tipo de animal, su método de prueba es visible en el mismo paquete o en cualquier subtipo. Si no lanzaste a Animal type, el código se compilará.

Espero que ayude

./ Arun

 0
Author: Arun,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-08-28 18:28:00