Modificador de acceso 'protegido' de Java

1. Información general

En el lenguaje de programación Java, los campos, constructores, métodos y clases se pueden marcar con modificadores de acceso. En este tutorial, veremos el acceso protegido .

2. La palabra clave protegida

Mientras que los elementos declarados como privados solo pueden ser accedidos por la clase en la que están declarados, la palabra clave protegida permite el acceso desde subclases y miembros del mismo paquete.

Al usar la palabra clave protegida , tomamos decisiones sobre qué métodos y campos deben considerarse internos de un paquete o jerarquía de clases y cuáles están expuestos a código externo.

3. Declaración de campos, métodos y constructores protegidos

Primero, creemos unclase denominada FirstClass que contiene un campo, método y constructor protegidos :

public class FirstClass { protected String name; protected FirstClass(String name) { this.name = name; } protected String getName() { return name; } }

Con este ejemplo, al usar la palabra clave protegida , hemos otorgado acceso a estos campos a clases en el mismo paquete que FirstClass y a subclases de FirstClass .

4. Acceso a campos, métodos y constructores protegidos

4.1 Del mismo paquete

Ahora, veamos cómo podemos acceder a los campos protegidos creando una nueva GenericClass declarada en el mismo paquete que FirstClass :

public class GenericClass { public static void main(String[] args) { FirstClass first = new FirstClass("random name"); System.out.println("FirstClass name is " + first.getName()); first.name = "new name"; } }

Como esta clase de llamada está en el mismo paquete que FirstClass, se le permite ver e interactuar con todos los campos, métodos y constructores protegidos .

4.2. De un paquete diferente

Intentemos ahora interactuar con estos campos de una clase declarada en un paquete diferente de FirstClass :

public class SecondGenericClass { public static void main(String[] args) { FirstClass first = new FirstClass("random name"); System.out.println("FirstClass name is "+ first.getName()); first.name = "new name"; } }

Como podemos ver, obtenemos errores de compilación :

The constructor FirstClass(String) is not visible The method getName() from the type FirstClass is not visible The field FirstClass.name is not visible

Eso es exactamente lo que esperábamos al usar la palabra clave protegida . Esto se debe a que SecondGenericClass no está en el mismo paquete que FirstClass y no lo subclasifica.

4.3 De una subclase

Veamos ahora qué sucede cuando declaramos una clase que extiende FirstClass pero declarada en un paquete diferente :

public class SecondClass extends FirstClass { public SecondClass(String name) { super(name); System.out.println("SecondClass name is " + this.getName()); this.name = "new name"; } }

Como era de esperar, podemos acceder a todos los campos, métodos y constructores protegidos. Esto se debe a que SecondClass es una subclase de FirstClass .

5. clase interior protegida

En los ejemplos anteriores, vimos campos, métodos y constructores protegidos en acción. Hay un caso más en particular: una clase interna protegida .

Creemos esta clase interna vacía dentro de nuestra FirstClass :

package com.baeldung.core.modifiers; public class FirstClass { // ... protected static class InnerClass { } }

Como podemos ver, esta es una clase interna estática, por lo que se puede construir desde fuera de una instancia de FirstClass . Sin embargo, como está protegido , solo podemos instanciarlo a partir del código del mismo paquete que FirstClass .

5.1 Del mismo paquete

Para probar esto, editemos nuestra GenericClass :

public class GenericClass { public static void main(String[] args) { // ... FirstClass.InnerClass innerClass = new FirstClass.InnerClass(); } }

Como podemos ver, podemos crear una instancia de InnerClass sin ningún problema porque GenericClass está en el mismo paquete que FirstClass .

5.2. De un paquete diferente

Intentemos crear una instancia de una InnerClass de nuestra SecondGenericClass que, como recordamos, está fuera del paquete FirstClass :

public class SecondGenericClass { public static void main(String[] args) { // ... FirstClass.InnerClass innerClass = new FirstClass.InnerClass(); } }

As expected, we get a compilation error:

The type FirstClass.InnerClass is not visible

5.3. From a Sub-Class

Let's try to do the same from our SecondClass:

public class SecondClass extends FirstClass { public SecondClass(String name) { // ... FirstClass.InnerClass innerClass = new FirstClass.InnerClass(); } }

We were expecting to instantiate our InnerClass with ease. However, we are getting a compilation error here too:

The constructor FirstClass.InnerClass() is not visible

Let's take a look at our InnerClass declaration:

protected static class InnerClass { }

The main reason we are getting this error is that the default constructor of a protected class is implicitly protected. In addition, SecondClassis a sub-class of FirstClass but is not a sub-class of InnerClass. Finally, we also declaredSecondClass outside FirstClass' package.

For all these reasons, SecondClass can't access the protectedInnerClass constructor.

Si quisiéramos resolver este problema y permitir que nuestra SecondClass instanciara un objeto InnerClass , podríamos declarar explícitamente un constructor público :

protected static class InnerClass { public InnerClass() { } }

Al hacer esto, ya no obtenemos un error de compilación y ahora podemos crear una instancia de una InnerClass desde SecondClass .

6. Conclusión

En este tutorial rápido, discutimos el modificador de acceso protegido en Java. Con él, podemos asegurarnos de exponer solo los datos y métodos requeridos a subclases y clases en el mismo paquete.

Como siempre, el código de ejemplo está disponible en GitHub.