¿Cuál es la diferencia entre public, protected, package-private y private en Java?

3171

En Java, hay reglas claras sobre cuándo utilizar cada uno de los modificadores de acceso, es decir, el valor por defecto (Programa privado), public, protectedy private, al tiempo que classy interfacey hacer frente a la herencia?

intrépido
fuente
161
privatese esconde de otras clases dentro del paquete. publicexpone a clases fuera del paquete. protectedes una versión publicrestringida solo a subclases.
Museful
87
@Tennenrishin - No; Contrariamente a C ++, en Java protectedel método también es accesible desde todo el paquete. Esta estupidez en el modelo de visibilidad de Java rompe el objetivo de protected.
Nicolas Barbulesco
35
@Nicolas Es accesible desde todo el paquete, con o sin protected. Como modificador de acceso , todo lo que protectedhace es exponerse a subclases fuera del paquete.
Museful
15
@tennenrishin - bueno, eso es lo que dijo Nicolas ... y lo estás repitiendo ahora. Lo que dijo originalmente fue que protected, y cito, 'es una versión de public restringida solo a subclases', lo cual no es cierto por su propia admisión, ya que protegido también permite el acceso a través de todo el paquete (ergo, no restringe el acceso a subclases. )
luis.espinal
10
También estoy de acuerdo con Nicolas en que el modo de acceso protegido en Java es idiota. Lo que sucedió es que Java combinó los calificadores de restricción de acceso horizontal (enrejado) y vertical. El alcance predeterminado es una restricción horizontal / reticular con la retícula como paquete. Público es otra restricción horizontal donde la red es el mundo entero. Privado y (C ++) protegido son verticales. Hubiera sido mejor si tuviéramos un acceso transversal, por ejemplo, protected-packagepara los casos raros donde realmente lo necesitábamos, dejando protectedque sea equivalente a la versión C ++ de protegido.
luis.espinal

Respuestas:

5639

El tutorial oficial puede ser de alguna utilidad para usted.

______________________________________________________________
El | │ Clase │ Paquete │ Subclase │ Subclase │ Mundo |
El | │ │ │ (mismo paquete) │ (paquete diferencial) │ |
| ───────────┼───────┼─────────┼──────────┼──────── ──┼──────── |
| público │ + │ + │ + │ + │ + | 
| ───────────┼───────┼─────────┼──────────┼──────── ──┼──────── |
| protegido │ + │ + │ + │ + │ | 
| ───────────┼───────┼─────────┼──────────┼──────── ──┼──────── |
| sin modificador│ + │ + │ + │ │ | 
| ───────────┼───────┼─────────┼──────────┼──────── ──┼──────── |
| privado │ + │ │ │ │ |
| ___________ | _______ | _________ | __________ | __________ | ________ |
 +: accesible en blanco: no accesible
David Segonds
fuente
55
La tabla anterior es incorrecta, ya que incluso los privatemiembros pueden ser vistos / utilizados por cualquier clase / método estático en el mismo archivo fuente.
Usagi Miyamoto
55
Solo se puede acceder al miembro protegido desde la subclase del mismo paquete, pero no desde la subclase de un paquete diferente. Debería haber una corrección en la tabla anterior
niks
2
El mundo está dentro de tu proyecto . Debería explicar más. Las bibliotecas están dentro de su proyecto, y si está creando una biblioteca, también expondrían estas clases y métodos públicos. Entonces, decir solo dentro de su proyecto está un poco fuera de lugar. "Todo lo que lo usa" es una mejor descripción.
adprocas
3
Por ejemplo, si tengo MyClassy estoy haciendo AnotherClass extends MyClass, tendré acceso a todos los métodos y propiedades protegidos y públicos desde dentro AnotherClass. Si lo hago MyClass myClass = new MyClass();en AnotherClassalgún lugar, digamos el constructor, solo tendré acceso a los métodos públicos si está en un paquete diferente. Tenga en cuenta que si lo hago = new MyClass() { @Override protected void protectedMethod() { //some logic } };, parece que puedo acceder a métodos protegidos, pero esto es lo mismo que extenderlo, pero en línea.
adprocas
3
Desafortunadamente, esta respuesta es una simplificación excesiva. La realidad es un poco más complicada, especialmente cuando lo consideras protected(que en realidad es un modificador de acceso bastante difícil de entender por completo; la mayoría de las personas que piensan que saben lo que protectedsignifica realmente no lo hacen) Además, como señaló Bohemian, no responde la pregunta: no dice nada sobre cuándo usar cada modificador de acceso. En mi opinión, esta respuesta no es lo suficientemente mala como para rechazar, pero sí cercana. ¿Pero más de 4000 votos a favor? ¿Cómo pasó esto?
Dawood ibn Kareem
483

(Advertencia: no soy un programador de Java, soy un programador de Perl. Perl no tiene protecciones formales, por eso quizás entiendo el problema tan bien :))

Privado

Como pensarías, solo la clase en la que se declara puede verlo.

Paquete privado

Solo puede ser visto y utilizado por el paquete en el que se declaró. Este es el valor predeterminado en Java (que algunos ven como un error).

Protegido

Package Private + puede ser visto por subclases o miembros del paquete.

Público

Todos pueden verlo.

Publicado

Visible fuera del código que controlo. (Si bien no es la sintaxis de Java, es importante para esta discusión).

C ++ define un nivel adicional llamado "amigo" y cuanto menos sepas sobre eso, mejor.

¿Cuándo deberías usar qué? La idea es encapsular para ocultar información. En la medida de lo posible, desea ocultar los detalles de cómo se hace algo de sus usuarios. ¿Por qué? Porque entonces puedes cambiarlos más tarde y no romper el código de nadie. Esto le permite optimizar, refactorizar, rediseñar y corregir errores sin preocuparse de que alguien esté usando ese código que acaba de revisar.

Entonces, la regla general es hacer que las cosas sean tan visibles como tienen que ser. Comience con privado y solo agregue más visibilidad según sea necesario. Solo haga público lo que es absolutamente necesario que el usuario sepa, cada detalle que haga público obstaculizará su capacidad para rediseñar el sistema.

Si desea que los usuarios puedan personalizar los comportamientos, en lugar de hacer públicos los elementos internos para que puedan anularlos, a menudo es una mejor idea meter esas tripas en un objeto y hacer pública esa interfaz. De esa manera, simplemente pueden enchufar un nuevo objeto. Por ejemplo, si estaba escribiendo un reproductor de CD y deseaba que el bit "ir a buscar información sobre este CD" fuera personalizable, en lugar de hacer públicos esos métodos, pondría toda esa funcionalidad en su propio objeto y haría público solo su objeto getter / setter . De esta manera, ser tacaño al exponer tus entrañas alienta una buena composición y separación de preocupaciones

Personalmente, me quedo con solo "privado" y "público". Muchos idiomas OO simplemente tienen eso. "Protegido" puede ser útil, pero es realmente un truco. Una vez que una interfaz es más que privada, está fuera de tu control y tienes que buscar en el código de otras personas para encontrar usos.

Aquí es donde entra en juego la idea de "publicado". Cambiar una interfaz (refactorizarla) requiere que encuentre todo el código que lo está usando y que también lo cambie. Si la interfaz es privada, no hay problema. Si está protegido, debes buscar todas tus subclases. Si es público, debe buscar todo el código que usa su código. A veces esto es posible, por ejemplo, si está trabajando en código corporativo que es solo para uso interno, no importa si una interfaz es pública. Puede obtener todo el código del repositorio corporativo. Pero si una interfaz se "publica", si hay un código que la usa fuera de su control, entonces está manguera. Debe admitir esa interfaz o arriesgarse a romper el código. Incluso las interfaces protegidas pueden considerarse publicadas (por eso no lo hago '

Muchos idiomas encuentran que la naturaleza jerárquica de público / protegido / privado es demasiado limitante y no está en línea con la realidad. Para ese fin, existe el concepto de una clase de rasgo , pero ese es otro espectáculo.

Schwern
fuente
26
amigos -> "Cuanto menos sepas, mejor" ---> Da visibilidad selectiva, que sigue siendo superior a la privacidad del paquete. En C ++, tiene sus usos, porque no todas las funciones pueden ser miembros, y amigos es mejor que publicitar. Por supuesto, existe el peligro de un mal uso por parte de las mentes malvadas.
Sebastian Mach
30
También se debe tener en cuenta que "protegido" en C ++ tiene un significado diferente: un método protegido es efectivamente privado, pero aún se puede llamar desde una clase heredada. (A diferencia de Java, donde puede ser llamado por cualquier clase dentro del mismo paquete.)
Rhys van der Waerden
99
@RhysvanderWaerden C # es lo mismo que C ++ en este aspecto. Me resulta bastante extraño que Java no permita declarar un miembro que sea accesible para la subclase pero no para todo el paquete. Para mí es algo al revés: ¡un paquete tiene un alcance más amplio que una clase secundaria!
Konrad Morawski
15
El paquete @KonradMorawski IMHO tiene un alcance menor que la subclase. Si no ha declarado su clase como final, los usuarios deberían poder subclasificarla, por lo que java protegido es parte de su interfaz publicada. OTOH, los paquetes son desarrollados implícitamente por una sola organización: por ejemplo, com.mycompany.mypackage. Si su código se declara en mi paquete, usted se declara implícitamente como parte de mi organización, por lo que deberíamos comunicarnos. Por lo tanto, el paquete se publica a un público más pequeño / más fácil de alcanzar (personas de mi empresa) que la subclase (personas que extienden mi objeto) y, por lo tanto, cuenta como una visibilidad más baja.
Eponymous
2
friendes bueno para definir relaciones especiales entre clases. Permite una encapsulación superior en muchos casos cuando se usa correctamente. Por ejemplo, puede ser utilizado por una clase de fábrica privilegiada para inyectar dependencias internas en un tipo construido. Tiene un mal nombre porque las personas que no se preocupan por mantener correctamente un modelo de objeto bien diseñado pueden abusar de él para facilitar su carga de trabajo.
Dennis
434

Aquí hay una mejor versión de la tabla, que también incluye una columna para módulos.

Modificadores de acceso Java

Explicaciones

  • Un miembro privado ( i) solo es accesible dentro de la misma clase que se declara.

  • Un miembro sin modificador de acceso ( j) solo es accesible dentro de las clases en el mismo paquete.

  • Se puede acceder a un miembro protegido ( k) dentro de todas las clases en el mismo paquete y dentro de las subclases en otros paquetes.

  • Un miembro público ( l) es accesible para todas las clases (a menos que resida en un módulo que no exporta el paquete en el que está declarado).


¿Qué modificador elegir?

Access Modifiers es una herramienta para ayudarlo a evitar romper accidentalmente la encapsulación (*) . Pregúntese si tiene la intención de que el miembro sea algo interno a la clase, paquete, jerarquía de clases o no interno, y elija el nivel de acceso correspondiente.

Ejemplos:

  • Un campo long internalCounterprobablemente debería ser privado ya que es mutable y un detalle de implementación.
  • Una clase que solo debe crearse una instancia en una clase de fábrica (en el mismo paquete) debe tener un constructor de paquete restringido, ya que no debería ser posible llamarlo directamente desde fuera del paquete.
  • void beforeRender()Debe protegerse un método interno llamado justo antes del renderizado y utilizado como un gancho en las subclases.
  • Un void saveGame(File dst)método que se llama desde el código GUI debe ser público.

(*) ¿Qué es exactamente la encapsulación?

aioobe
fuente
11
Solo digo: hay muchas personas que tienen problemas para distinguir el color rojo / verde. Las tablas que usan esquemas de color rojo / verde (o amarillo / naranja / ...) rara vez son "mejores" en nada ;-)
GhostCat
1
@ GhostCat, no estoy de acuerdo. Creo que el rojo / verde se alinea intuitivamente con "funciona" / "no funciona" para muchas personas, es decir, es mejor que muchas alternativas.
aioobe
8
colourblindawareness.org/colour-blindness/… ... El 8% de los hombres daltónicos se puede dividir aproximadamente en 1% deuteranopes, 1% protanopes, 1% protanomalous y 5% deuteranomalous . Y como soy uno de esos 50% de ese 5%, puede estar seguro: rojo / verde apesta.
GhostCat
66
@GhostCat Ok ... esa es una mayor parte de la población de lo que esperaba. Subí la imagen en este simulador de daltonismo y probé todos los modos diferentes. Incluso en modo monocromía / acromatopsia, la diferencia de color es razonable. ¿Puedes ver la diferencia o el simulador está apagado? (Estoy siendo de la opinión que el rojo / verde es muy intuitiva para la gente ver en color.)
aioobe
3
Puedo ver la diferencia, pero también puedo pasar la mitad de las pruebas de daltonismo que tenemos que hacer en Alemania para obtener la licencia de conducir ;-) ... pero creo que ese simulador es "lo suficientemente bueno".
GhostCat
206
____________________________________________________________________
                | highest precedence <---------> lowest precedence
*———————————————+———————————————+———————————+———————————————+———————
 \ xCanBeSeenBy | this          | any class | this subclass | any
  \__________   | class         | in same   | in another    | class
             \  | nonsubbed     | package   | package       |    
Modifier of x \ |               |           |               |       
————————————————*———————————————+———————————+———————————————+———————
public          |              |          |              |     
————————————————+———————————————+———————————+———————————————+———————
protected       |              |          |              |      
————————————————+———————————————+———————————+———————————————+———————
package-private |               |           |               |
(no modifier)   |              |          |              |      
————————————————+———————————————+———————————+———————————————+———————
private         |              |          |              |       
____________________________________________________________________
Abdull
fuente
1
Vale la pena poner en palabras: "El modificador protegido hace que el objeto esté disponible en otros paquetes, mientras que el valor predeterminado / sin modificador restringe el acceso al mismo paquete"
vanguard6969
2
@ vanguard69, el protectedmodificador hace que la cosa marcada (clase, método o campo) esté disponible para otra clase en algún otro paquete solo si dicha otra clase es una subclase de la clase donde se declara esa cosaprotected marcada .
Abdull
"no subido"? "esta subclase en otro paquete"? Huh Pensé que conocía Java.
sehe
@AlexanderFarber, ¿optimizaste para una configuración de navegador en particular? Este es mi Chrome ahora y este es Firefox
Sehe
Hmm vamos a revertir mi cambio entonces
Alexander Farber
165

Regla fácil Comience declarando todo privado. Y luego avance hacia el público a medida que surjan las necesidades y el diseño lo amerite.

Al exponer a los miembros, pregúntese si está exponiendo opciones de representación u opciones de abstracción. El primero es algo que desea evitar, ya que introducirá demasiadas dependencias en la representación real en lugar de en su comportamiento observable.

Como regla general, trato de evitar anular las implementaciones de métodos subclasificando; Es demasiado fácil arruinar la lógica. Declare métodos protegidos abstractos si tiene la intención de anularlos.

Además, use la anotación @Override al anular para evitar que las cosas se rompan cuando refactorice.

John Nilsson
fuente
3
@RuchirBaronia, "mundo" = todo el código de la aplicación, independientemente de dónde se encuentre.
Andrejs
116

En realidad es un poco más complicado que una simple cuadrícula muestra. La cuadrícula le dice si se permite un acceso, pero ¿qué constituye exactamente un acceso? Además, los niveles de acceso interactúan con clases anidadas y herencia de formas complejas.

El acceso "predeterminado" (especificado por la ausencia de una palabra clave) también se denomina paquete privado . Excepción: en una interfaz, ningún modificador significa acceso público; Los modificadores que no sean públicos están prohibidos. Las constantes de enumeración son siempre públicas.

Resumen

¿Se permite el acceso a un miembro con este especificador de acceso?

  • Miembro es private: solo si el miembro se define dentro de la misma clase que el código de llamada.
  • El miembro es un paquete privado: solo si el código de llamada está dentro del paquete adjunto inmediato del miembro.
  • Miembro es protected: el mismo paquete, o si el miembro se define en una superclase de la clase que contiene el código de llamada.
  • El miembro es public: sí.

A qué especificadores de acceso se aplican

Las variables locales y los parámetros formales no pueden tomar especificadores de acceso. Dado que son inherentemente inaccesibles al exterior de acuerdo con las reglas de alcance, son efectivamente privados.

Para clases en el ámbito superior, solo publicse permiten paquetes y paquetes privados. Esta opción de diseño es presumiblemente debido protectedy privatesería redundante a nivel de paquete (no hay herencia de paquetes).

Todos los especificadores de acceso son posibles en miembros de la clase (constructores, métodos y funciones miembro estáticas, clases anidadas).

Relacionado: Accesibilidad de clase Java

Orden

Los especificadores de acceso se pueden ordenar estrictamente

público> protegido> paquete-privado> privado

lo que significa que publicproporciona el mayor acceso, privateel menor. Cualquier referencia posible en un miembro privado también es válida para un miembro privado de paquete; cualquier referencia a un miembro privado del paquete es válida en un miembro protegido, y así sucesivamente. (Dar acceso a miembros protegidos a otras clases en el mismo paquete se consideró un error).

Notas

  • Métodos de una clase están autorizados a acceder a miembros privados de otros objetos de la misma clase. Más precisamente, un método de clase C puede acceder a miembros privados de C en objetos de cualquier subclase de C. Java no admite restringir el acceso por instancia, solo por clase. (Compárese con Scala, que lo admite usando private[this]).
  • Necesita acceso a un constructor para construir un objeto. Por lo tanto, si todos los constructores son privados, la clase solo se puede construir mediante código que viva dentro de la clase (generalmente métodos de fábrica estáticos o inicializadores de variables estáticas). Del mismo modo para constructores privados o protegidos por paquetes.
    • Solo tener constructores privados también significa que la clase no se puede subclasificar externamente, ya que Java requiere que los constructores de una subclase llamen implícita o explícitamente un constructor de superclase. (Sin embargo, puede contener una clase anidada que la subclasifique).

Clases internas

También debe tener en cuenta los ámbitos anidados , como las clases internas. Un ejemplo de la complejidad es que las clases internas tienen miembros, que pueden tomar modificadores de acceso. Entonces puedes tener una clase interna privada con un miembro público; ¿Se puede acceder al miembro? (Ver abajo). La regla general es mirar el alcance y pensar recursivamente para ver si puede acceder a cada nivel.

Sin embargo, esto es bastante complicado, y para más detalles, consulte la Especificación del lenguaje Java . (Sí, ha habido errores de compilación en el pasado).

Para ver cómo interactúan, considere este ejemplo. Es posible "filtrar" clases internas privadas; esto suele ser una advertencia:

class Test {
    public static void main(final String ... args) {
        System.out.println(Example.leakPrivateClass()); // OK
        Example.leakPrivateClass().secretMethod(); // error
    }
}

class Example {
    private static class NestedClass {
        public void secretMethod() {
            System.out.println("Hello");
        }
    }
    public static NestedClass leakPrivateClass() {
        return new NestedClass();
    }
}

Salida del compilador:

Test.java:4: secretMethod() in Example.NestedClass is defined in an inaccessible class or interface
        Example.leakPrivateClass().secretMethod(); // error
                                  ^
1 error

Algunas preguntas relacionadas:

Caracol mecánico
fuente
1
"los modificadores que no sean públicos están prohibidos" - a partir de Java 9, este ya no es el caso: las interfaces también pueden tener métodos privados.
MC Emperor
96

Como una regla de oro:

  • private: alcance de clase.
  • default(o package-private): alcance del paquete.
  • protected: package scope + child(como paquete, pero podemos subclasificarlo de diferentes paquetes). El modificador protegido siempre mantiene la relación "padre-hijo".
  • public: En todas partes.

Como resultado, si dividimos el derecho de acceso en tres derechos:

  • (D) irect (invocar desde un método dentro de la misma clase, o mediante la sintaxis "this").
  • (R) eferencia (invoque un método usando una referencia a la clase, o mediante la sintaxis "punto").
  • (I) herencia (a través de subclases).

entonces tenemos esta tabla simple:

+—-———————————————+————————————+———————————+
|                 |    Same    | Different |
|                 |   Package  | Packages  |
+—————————————————+————————————+———————————+
| private         |   D        |           |
+—————————————————+————————————+———————————+
| package-private |            |           |
| (no modifier)   |   D R I    |           |
+—————————————————+————————————+———————————+
| protected       |   D R I    |       I   |
+—————————————————+————————————+———————————+
| public          |   D R I    |    R  I   |
+—————————————————+————————————+———————————+
nxhoaf
fuente
54

En muy corto

  • public: accesible desde cualquier lugar.
  • protected: accesible por las clases del mismo paquete y las subclases que residen en cualquier paquete.
  • predeterminado (sin modificador especificado): accesible por las clases del mismo paquete.
  • private: accesible solo dentro de la misma clase.
Ravi
fuente
48

El modificador de acceso más incomprendido en Java es protected. Sabemos que es similar al modificador predeterminado con una excepción en la que las subclases pueden verlo. ¿Pero cómo? Aquí hay un ejemplo que, con suerte, aclara la confusión:

  • Supongamos que tenemos 2 clases; Fathery Son, cada uno en su propio paquete:

    package fatherpackage;
    
    public class Father
    {
    
    }
    
    -------------------------------------------
    
    package sonpackage;
    
    public class Son extends Father
    {
    
    }
  • Agreguemos un método protegido foo()a Father.

    package fatherpackage;
    
    public class Father
    {
        protected void foo(){}
    }
  • El método foo()se puede llamar en 4 contextos:

    1. Dentro de una clase que se encuentra en el mismo paquete donde foo()se define ( fatherpackage):

      package fatherpackage;
      
      public class SomeClass
      {
          public void someMethod(Father f, Son s)
          {
              f.foo();
              s.foo();
          }
      }
    2. Dentro de una subclase, en la instancia actual a través de thiso super:

      package sonpackage;
      
      public class Son extends Father
      {
          public void sonMethod()
          {
              this.foo();
              super.foo();
          }
      }
    3. En una referencia cuyo tipo es la misma clase:

      package fatherpackage;
      
      public class Father
      {
          public void fatherMethod(Father f)
          {
              f.foo(); // valid even if foo() is private
          }
      }
      
      -------------------------------------------
      
      package sonpackage;
      
      public class Son extends Father
      {
          public void sonMethod(Son s)
          {
              s.foo();
          }
      }
    4. En una referencia cuyo tipo es la clase padre y está dentro del paquete donde foo()se define ( fatherpackage) [Esto se puede incluir dentro del contexto no. 1]:

      package fatherpackage;
      
      public class Son extends Father
      {
          public void sonMethod(Father f)
          {
              f.foo();
          }
      }
  • Las siguientes situaciones no son válidas.

    1. En una referencia cuyo tipo es la clase padre y está fuera del paquete donde foo()se define ( fatherpackage):

      package sonpackage;
      
      public class Son extends Father
      {
          public void sonMethod(Father f)
          {
              f.foo(); // compilation error
          }
      }
    2. Una no subclase dentro de un paquete de una subclase (una subclase hereda los miembros protegidos de su padre y los hace privados a las no subclases):

      package sonpackage;
      
      public class SomeClass
      {
          public void someMethod(Son s) throws Exception
          {
              s.foo(); // compilation error
          }
      }
Eng.Fouad
fuente
Object#clone()Es un ejemplo de un protectedmiembro.
Eng.Fouad
¿Cuál es la diferencia entre hacer super.foo()y la primera situación inválida f.foo()?
cst1992
1
@ cst1992 Es confuso, pero consulte la Especificación 6.6.2 del lenguaje Java: "Se puede acceder a un miembro o constructor protegido de un objeto desde fuera del paquete en el que se declara solo por el código responsable de la implementación de ese objeto". Con super.foo () la referencia "super" es "directamente responsable de la implementación" pero la referencia "f" no lo es. ¿Por qué? Porque puedes estar 100% seguro de que "super" es del tipo padre, pero no de "f"; en tiempo de ejecución podría ser algún otro subtipo de padre. Ver docs.oracle.com/javase/specs/jls/se9/html/…
skomisa
1
Es refrescante leer una respuesta de alguien que entiende protected. Desafortunadamente, todas las otras respuestas en esta página que definen protectedse equivocan un poco.
Dawood ibn Kareem
30

Privado

  • Métodos, Variables y Constructores

Solo se puede acceder a los métodos, variables y constructores que se declaran privados dentro de la clase declarada.

  • Clase e interfaz

El modificador de acceso privado es el nivel de acceso más restrictivo. La clase y las interfaces no pueden ser privadas.

Nota

Se puede acceder a las variables que se declaran privadas fuera de la clase si los métodos públicos de obtención están presentes en la clase. Las subclases de otro paquete o cualquier clase dentro del paquete de la clase de miembros protegidos solo pueden acceder a las variables, métodos y constructores que se declaran protegidos en una superclase.


Protegido

  • Clase e interfaz

El modificador de acceso protegido no se puede aplicar a clases e interfaces.

Los métodos y los campos se pueden declarar protegidos, sin embargo, los métodos y los campos en una interfaz no se pueden declarar protegidos.

Nota

El acceso protegido le da a la subclase la oportunidad de usar el método auxiliar o variable, al tiempo que evita que una clase no relacionada intente usarlo.


Público

Se puede acceder a una clase, método, constructor, interfaz, etc. declarado público desde cualquier otra clase.

Por lo tanto, se puede acceder a los campos, métodos y bloques declarados dentro de una clase pública desde cualquier clase que pertenezca al Universo Java.

  • Diferentes paquetes

Sin embargo, si la clase pública a la que intentamos acceder está en un paquete diferente, entonces la clase pública aún debe importarse.

Debido a la herencia de clase, todos sus métodos y variables públicas de una clase son heredados por sus subclases.


Predeterminado -No palabra clave:

El modificador de acceso predeterminado significa que no declaramos explícitamente un modificador de acceso para una clase, campo, método, etc.

  • Dentro de los mismos paquetes

Una variable o método declarado sin ningún modificador de control de acceso está disponible para cualquier otra clase en el mismo paquete. Los campos en una interfaz son implícitamente públicos estáticos finales y los métodos en una interfaz son públicos por defecto.

Nota

No podemos anular los campos estáticos. Si intenta anularlo, no muestra ningún error, pero no funciona lo que exceptuamos.

Respuestas relacionadas

Enlaces de referencias

http://docs.oracle.com/javase/tutorial/java/javaOO/accesscontrol.html http://www.tutorialspoint.com/java/java_access_modifiers.htm

Nambi
fuente
21

La diferencia se puede encontrar en los enlaces ya proporcionados, pero cuál usar generalmente se reduce al "Principio de Menos Conocimiento". Solo permita la menor visibilidad necesaria.

Joe Phillips
fuente
20

Privado : acceso limitado a clase solamente

Predeterminado (sin modificador) : acceso limitado a la clase y al paquete

Protegido : acceso limitado a clase, paquete y subclases (tanto dentro como fuera del paquete)

Público : accesible a la clase, paquete (todos) y subclases ... En resumen, en todas partes.

samkit shah
fuente
17

Los modificadores de acceso están ahí para restringir el acceso en varios niveles.

Público: es básicamente tan simple como puede acceder desde cualquier clase, ya sea que esté en el mismo paquete o no.

Para acceder si está en el mismo paquete, puede acceder directamente, pero si está en otro paquete, puede crear un objeto de la clase.

Valor predeterminado: se puede acceder en el mismo paquete desde cualquiera de la clase de paquete.

Para acceder puede crear un objeto de la clase. Pero no puede acceder a esta variable fuera del paquete.

Protegido: puede acceder a las variables en el mismo paquete, así como a la subclase en cualquier otro paquete. así que básicamente es el comportamiento predeterminado + heredado .

Para acceder al campo protegido definido en la clase base, puede crear un objeto de clase secundaria.

Privado: se puede acceder en la misma clase.

En métodos no estáticos, puede acceder directamente debido a esta referencia (también en constructores), pero para acceder en métodos estáticos necesita crear objetos de la clase.

Prasante
fuente
16

Modificadores de acceso en Java.

Los modificadores de acceso de Java se utilizan para proporcionar control de acceso en Java.

1. Predeterminado:

Accesible a las clases en el mismo paquete solamente.

Por ejemplo,

// Saved in file A.java
package pack;

class A{
  void msg(){System.out.println("Hello");}
}

// Saved in file B.java
package mypack;
import pack.*;

class B{
  public static void main(String args[]){
   A obj = new A(); // Compile Time Error
   obj.msg(); // Compile Time Error
  }
}

Este acceso es más restringido que público y protegido, pero menos restringido que privado.

2. Público

Se puede acceder desde cualquier lugar. (Acceso global)

Por ejemplo,

// Saved in file A.java

package pack;
public class A{
  public void msg(){System.out.println("Hello");}
}

// Saved in file B.java

package mypack;
import pack.*;

class B{
  public static void main(String args[]){
    A obj = new A();
    obj.msg();
  }
}

Salida: hola

3. Privado

Accesible solo dentro de la misma clase.

Si intenta acceder a miembros privados en una clase en otra, arrojará un error de compilación. Por ejemplo,

class A{
  private int data = 40;
  private void msg(){System.out.println("Hello java");}
}

public class Simple{
  public static void main(String args[]){
    A obj = new A();
    System.out.println(obj.data); // Compile Time Error
    obj.msg(); // Compile Time Error
  }
}

4. Protegido

Accesible solo a las clases en el mismo paquete y a las subclases

Por ejemplo,

// Saved in file A.java
package pack;
public class A{
  protected void msg(){System.out.println("Hello");}
}

// Saved in file B.java
package mypack;
import pack.*;

class B extends A{
  public static void main(String args[]){
    B obj = new B();
    obj.msg();
  }
}

Salida: hola

Ingrese la descripción de la imagen aquí

Affy
fuente
14
  • público : accesible desde cualquier lugar de la aplicación.

  • predeterminado : accesible desde el paquete.

  • protegido : accesible desde el paquete y las subclases en otro paquete. también

  • privado : accesible solo desde su clase.

Shailendra Singh
fuente
14

Visible para el paquete. El valor por defecto. No se necesitan modificadores.

Visible solo para la clase ( privado ).

Visible al mundo ( público ).

Visible para el paquete y todas las subclases ( protegido ).

Las variables y los métodos se pueden declarar sin ningún modificador que se llame. Ejemplos predeterminados:

String name = "john";

public int age(){
    return age;
}

Modificador de acceso privado - privado:

Solo se puede acceder a los métodos, variables y constructores que se declaran privados dentro de la clase declarada. El modificador de acceso privado es el nivel de acceso más restrictivo. La clase y las interfaces no pueden ser privadas.

Se puede acceder a las variables que se declaran privadas fuera de la clase si los métodos públicos de obtención están presentes en la clase.

El uso del modificador privado es la forma principal en que un objeto se encapsula y oculta datos del mundo exterior.

Ejemplos:

Public class Details{

    private String name;

    public void setName(String n){
        this.name = n;
    }

    public String getName(){
        return this.name;
    }
}

Modificador de acceso público - público:

Se puede acceder a una clase, método, constructor, interfaz, etc. declarado público desde cualquier otra clase. Por lo tanto, se puede acceder a los campos, métodos y bloques declarados dentro de una clase pública desde cualquier clase que pertenezca al universo Java.

Sin embargo, si la clase pública a la que intentamos acceder está en un paquete diferente, entonces la clase pública aún debe importarse.

Debido a la herencia de clase, todos sus métodos y variables públicas de una clase son heredados por sus subclases.

Ejemplo:

public void cal(){

}

Modificador de acceso protegido - protegido:

Las subclases de otro paquete o cualquier clase dentro del paquete de la clase de miembros protegidos solo pueden acceder a las variables, métodos y constructores que se declaran protegidos en una superclase.

El modificador de acceso protegido no se puede aplicar a clases e interfaces. Los métodos y los campos se pueden declarar protegidos, sin embargo, los métodos y los campos en una interfaz no se pueden declarar protegidos.

El acceso protegido le da a la subclase la oportunidad de usar el método auxiliar o variable, al tiempo que evita que una clase no relacionada intente usarlo.

class Van{

    protected boolean speed(){

    }
}

class Car{
    boolean speed(){
    }

}
amila isura
fuente
12

Esta página escribe bien sobre el modificador de acceso protegido y predeterminado

.... Protegido: el modificador de acceso protegido es un poco complicado y se puede decir que es un superconjunto del modificador de acceso predeterminado. Los miembros protegidos son los mismos que los miembros predeterminados en lo que respecta al acceso en el mismo paquete. La diferencia es que los miembros protegidos también son accesibles para las subclases de la clase en la que se declara el miembro que están fuera del paquete en el que está presente la clase principal.

Pero estos miembros protegidos son "accesibles fuera del paquete solo a través de la herencia". es decir, puede acceder a un miembro protegido de una clase en su subclase presente en algún otro paquete directamente como si el miembro estuviera presente en la propia subclase. Pero ese miembro protegido no será accesible en la subclase fuera del paquete utilizando la referencia de la clase padre. ....

dameng
fuente
Solo para agregar esto "Una vez que el niño obtiene acceso al miembro protegido de la clase padre, se vuelve privado (o más bien diría que un miembro privado especial que puede ser heredado por las subclases de la subclase) miembro de la subclase".
Anand
9

La respuesta de David proporciona el significado de cada modificador de acceso. En cuanto a cuándo usar cada uno, sugeriría hacer públicas todas las clases y los métodos de cada clase que están destinados para uso externo (su API) y todo lo demás privado.

Con el tiempo, desarrollará una idea de cuándo hacer que algunas clases sean privadas de paquetes y cuándo declarar ciertos métodos protegidos para su uso en subclases.

Dov Wasserman
fuente
6

Nota: Esto es solo un suplemento para la respuesta aceptada.

Esto está relacionado con los modificadores de acceso Java .

Desde modificadores de acceso Java :

Un modificador de acceso Java especifica qué clases pueden acceder a una clase dada y sus campos, constructores y métodos. Los modificadores de acceso se pueden especificar por separado para una clase, sus constructores, campos y métodos. Los modificadores de acceso Java también se denominan a veces en el habla diaria como especificadores de acceso Java, pero el nombre correcto es modificadores de acceso Java. Las clases, campos, constructores y métodos pueden tener uno de cuatro modificadores de acceso Java diferentes:

  • Elemento de la lista
  • privado
  • predeterminado (paquete)
  • protegido
  • público

Desde tutoriales de control de acceso a miembros de una clase :

Los modificadores de nivel de acceso determinan si otras clases pueden usar un campo en particular o invocar un método en particular. Hay dos niveles de control de acceso:

  • En el nivel superior: público o paquete privado (sin modificador explícito).
  • A nivel de miembro: público, privado, protegido o paquete privado (sin modificador explícito).

Se puede declarar una clase con el modificador public, en cuyo caso esa clase es visible para todas las clases en todas partes. Si una clase no tiene un modificador (el valor predeterminado, también conocido como paquete privado), solo es visible dentro de su propio paquete

La siguiente tabla muestra el acceso a los miembros permitido por cada modificador.

╔═════════════╦═══════╦═════════╦══════════╦═══════╗
 Modifier     Class  Package  Subclass  World 
╠═════════════╬═══════╬═════════╬══════════╬═══════╣
 public       Y      Y        Y         Y     
 protected    Y      Y        Y         N     
 no modifier  Y      Y        N         N     
 private      Y      N        N         N     
╚═════════════╩═══════╩═════════╩══════════╩═══════╝

La primera columna de datos indica si la clase misma tiene acceso al miembro definido por el nivel de acceso. Como puede ver, una clase siempre tiene acceso a sus propios miembros. La segunda columna indica si las clases en el mismo paquete que la clase (independientemente de su origen) tienen acceso al miembro. La tercera columna indica si las subclases de la clase declarada fuera de este paquete tienen acceso al miembro. La cuarta columna indica si todas las clases tienen acceso al miembro.

Los niveles de acceso te afectan de dos maneras. Primero, cuando usa clases que provienen de otra fuente, como las clases en la plataforma Java, los niveles de acceso determinan qué miembros de esas clases pueden usar sus propias clases. En segundo lugar, cuando escribe una clase, debe decidir qué nivel de acceso debe tener cada variable miembro y cada método de su clase.

ישו אוהב אותך
fuente
1
¿Cuál es exactamente el suplemento y por qué no es una edición de la publicación existente?
sehe
el suplemento es modificadores de acceso. ¿Por qué no una edición? Mantener inalterada la respuesta aceptada por razones históricas y dar mi respuesta.
ישו אוהב אותך
5

Public Protected Default y private son modificadores de acceso.

Están destinados a encapsular u ocultar y mostrar contenidos de la clase.

  1. La clase puede ser pública o predeterminada
  2. Los miembros de la clase pueden ser públicos, protegidos, predeterminados o privados.

No se puede acceder a Private fuera de la clase. Solo se puede acceder a Default en el paquete. Protegido en el paquete, así como en cualquier clase que lo extienda. El público está abierto para todos.

Normalmente, las variables miembro se definen privadas, pero los métodos miembros son públicos.

richa_v
fuente
Defaultno es un modificador de acceso, y dos de los otros están mal escritos.
Marqués de Lorne
5

Muchas veces me he dado cuenta de que recordar los conceptos básicos de cualquier lenguaje puede ser posible creando analogías del mundo real. Aquí está mi analogía para comprender los modificadores de acceso en Java:

Supongamos que eres estudiante en una universidad y tienes un amigo que viene a visitarte durante el fin de semana. Supongamos que existe una gran estatua del fundador de la universidad en el medio del campus.

  • Cuando lo traes al campus, lo primero que tú y tu amigo ven es esta estatua. Esto significa que cualquiera que camine en el campus puede mirar la estatua sin el permiso de la universidad. Esto hace que la estatua sea PÚBLICA .

  • Luego, desea llevar a su amigo a su dormitorio, pero para eso debe registrarlo como visitante. Esto significa que obtiene un pase de acceso (que es el mismo que el tuyo) para ingresar a varios edificios en el campus. Esto haría que su tarjeta de acceso fuera PROTEGIDA .

  • Su amigo quiere iniciar sesión en el WiFi del campus, pero no tiene las credenciales para hacerlo. La única forma en que puede conectarse es si comparte su nombre de usuario con él. (Recuerde, cada estudiante que va a la universidad también posee estas credenciales de inicio de sesión). Esto haría que sus credenciales de inicio de sesión como NO MODIFICADOR .

  • Finalmente, su amigo quiere leer su informe de progreso para el semestre que se publica en el sitio web. Sin embargo, cada estudiante tiene su propio inicio de sesión personal para acceder a esta sección del sitio web del campus. Esto haría que estas credenciales fueran PRIVADAS .

¡Espero que esto ayude!

Codificador codicioso
fuente
4

Cuando esté pensando en modificadores de acceso, piénselo de esta manera (se aplica tanto a las variables como a los métodos ):

public-> accesible desde cualquier lugar
private-> accesible solo dentro de la misma clase donde se declara

Ahora surge la confusión cuando se trata de defaultyprotected

default-> No hay una palabra clave modificadora de acceso presente. Esto significa que está disponible estrictamente dentro del paquete de la clase. No se puede acceder a ninguna parte fuera de ese paquete.

protected-> Un poco menos estricto que, defaulty aparte de las mismas clases de paquetes, se puede acceder por subclases fuera del paquete que se declara.

Pritam Banerjee
fuente
4

El acceso a Java modifica cuál puede usar

ingrese la descripción de la imagen aquí

Modificador de acceso puede ser aplicable para class, field[Sobre] , method. Intenta acceder, subclase o anular esto.

  • El acceso fieldao methodes a través de a class.
  • Herencia. El classmodificador de acceso sucesor (subclase) puede ser cualquiera. El methodmodificador de acceso sucesor (anulación) debe ser el mismo o expandirlo

La clase de nivel superior (alcance de primer nivel) puede ser publicy default. Nested class[Acerca de] puede tener cualquiera de ellos

package no se aplica a la jerarquía de paquetes

Modificadores de acceso rápido

yoAlex5
fuente
2

Se trata de encapsulación (o como dijo Joe Phillips, menos conocimiento ).

Comience con el más restrictivo (privado) y vea si necesita modificadores menos restrictivos más adelante.

Todos usamos métodos y modificadores de miembros como privado, público, ... pero una cosa que muy pocos desarrolladores hacen es usar paquetes para organizar el código lógicamente.

Por ejemplo: puede poner métodos de seguridad sensibles en un paquete de 'seguridad'. Luego, coloque una clase pública que acceda a parte del código relacionado con la seguridad en este paquete, pero mantenga privado el paquete de otras clases de seguridad . Por lo tanto, otros desarrolladores solo podrán usar la clase disponible públicamente desde fuera de este paquete (a menos que cambien el modificador). Esta no es una característica de seguridad, pero guiará el uso.

Outside world -> Package (SecurityEntryClass ---> Package private classes)

Otra cosa es que las clases que dependen mucho unas de otras pueden terminar en el mismo paquete y eventualmente podrían refactorizarse o fusionarse si la dependencia es demasiado fuerte.

Si, por el contrario, establece todo como público , no estará claro a qué se debe acceder o no, lo que puede conducir a escribir mucho javadoc (que no impone nada a través del compilador ...).

Christophe Roussy
fuente
2

privado-protegido-público-perfecto-analogía-para-los-tipos-de-datos-variables

El siguiente diagrama de bloques explica cómo se heredan los miembros de datos de la clase base cuando el modo de acceso a la clase derivada es privado .

ingrese la descripción de la imagen aquí

Nota: la declaración de miembros de datos con especificador de acceso privado se conoce como ocultación de datos.

Fuente: Especificadores de acceso: privados, públicos y protegidos

leonidaa
fuente
1
La pregunta era sobre Java, no sobre C ++.
Benoit
1
@Benoit Pero lo que he publicado, las imágenes en especial, no son lo mismo para ambos: java y c ++, ¿estas reglas tampoco se aplican a java? gracias
leonidaa
2
En C ++ solo hay 3 modificadores, mientras que hay 4 en java.
Benoit el
1
la analogía es buena, pero falta el especificador de acceso predeterminado,
mss
1
OP hizo la pregunta "¿Cuál es la diferencia entre público, protegido, paquete privado y privado en Java?"
JL_SO
2

Mis dos centavos :)

privado:

clase -> una clase de nivel superior no puede ser privada. Las clases internas pueden ser privadas a las que se puede acceder desde la misma clase.

variable de instancia -> accesible solo en la clase. No se puede acceder fuera de la clase.

paquete privado:

clase -> una clase de nivel superior puede ser privada del paquete. Solo se puede acceder desde el mismo paquete. No del subpaquete, no del paquete externo.

variable de instancia -> accesible desde el mismo paquete. No del subpaquete, no del paquete externo.

protegido:

clase -> una clase de nivel superior no se puede proteger.

variable de instancia -> Solo accesible en el mismo paquete o subpaquete. Solo se puede acceder fuera del paquete mientras se extiende la clase.

público:

clase -> accesible desde paquete / subpaquete / otro paquete

variable de instancia -> accesible desde paquete / subpaquete / otro paquete

Aquí está la respuesta detallada

https://github.com/junto06/java-4-beginners/blob/master/basics/access-modifier.md

Mudassar
fuente
1
  • público

    Si un miembro de la clase se declara con public, entonces se puede acceder desde cualquier lugar

  • protegido

    Si un miembro de la clase se declara con una palabra clave protegida, se puede acceder desde los mismos miembros de la clase, miembros de la clase externos dentro del mismo paquete y miembros de la clase heredados. Si un miembro de la clase está protegido, entonces NO se puede acceder desde la clase de paquete externa a menos que la clase de paquete externa se herede, es decir, amplíe la otra superclase de paquete. Pero un miembro de clase protegido siempre está disponible para las mismas clases de paquete, NO importa si la misma clase de paquete se hereda o NO

  • defecto

    En Java, el valor predeterminado NO es una palabra clave de modificador de acceso. Si un miembro de la clase se declara sin ninguna palabra clave modificadora de acceso, en este caso se considera como miembro predeterminado. El miembro de clase predeterminado siempre está disponible para los mismos miembros de clase de paquete. Pero el miembro de la clase de paquete externo NO puede acceder a los miembros de clase predeterminados incluso si las clases externas son subclases a diferencia de los miembros protegidos

  • privado

    Si un miembro de la clase se declara con una palabra clave protegida, en este caso está disponible SOLO para los mismos miembros de la clase

alexvipul
fuente
-1

Especificadores de acceso en Java: hay 4 especificadores de acceso en java, a saber, privado, paquete privado (predeterminado), protegido y público en orden de acceso creciente.

Privado : cuando está desarrollando alguna clase y desea que un miembro de esta clase no quede expuesto fuera de esta clase, debe declararlo como privado. Se puede acceder a los miembros privados solo en la clase donde están definidos, es decir, encerrando la clase. Se puede acceder a los miembros privados en 'esta' referencia y también en otras instancias de clase que incluyen a estos miembros, pero solo dentro de la definición de esta clase.

Paquete privado (predeterminado) : este especificador de acceso proporcionará el acceso especificado por el especificador de acceso privado además del acceso que se describe a continuación.

Cuando está desarrollando algún paquete y, por lo tanto, alguna clase (por ejemplo, Clase1) dentro de él, puede usar el especificador de acceso predeterminado (no es necesario mencionarlo explícitamente), para exponer al miembro dentro de la clase, a otras clases dentro de su (mismo) paquete. En estas otras clases (dentro del mismo paquete), puede acceder a estos miembros predeterminados en la instancia de Class1. También puede acceder a estos miembros predeterminados dentro de las subclases de Class1, digamos Class2 (en esta referencia o en la instancia de Class1 o en la instancia de Class2).

Básicamente, dentro del mismo paquete puede acceder a los miembros predeterminados en la instancia de clase directamente o en 'esta' referencia en subclases.

protegido : este especificador de acceso proporcionará el acceso especificado por el especificador de acceso privado del paquete además del acceso que se describe a continuación.

Cuando desarrolle algún paquete y, por lo tanto, alguna clase (por ejemplo, Clase1) dentro de él, debe usar un especificador de acceso protegido para el miembro de datos dentro de Clase1 si no desea que se acceda a este miembro fuera de su paquete (por ejemplo, en el paquete del consumidor de su paquete (es decir, el cliente que usa sus API) en general, pero desea hacer una excepción y permitir el acceso a este miembro solo si el cliente escribe una clase, digamos Clase2, que extiende Clase1. Por lo tanto, en general, los miembros protegidos serán accesibles en 'esta' referencia en clases derivadas, es decir, Clase2 y también en instancias explícitas de Clase2.

Tenga en cuenta:

  1. No podrá acceder al miembro protegido heredado de Class1 en Class2, si intenta acceder a él en una instancia explícita de Class1, aunque se hereda en él.
  2. Cuando escribe otra clase Class3 dentro del mismo / diferente paquete que extiende Class2, el miembro protegido de Class1 estará accesible en esta referencia y también en la instancia explícita de Class3. Esto será cierto para cualquier jerarquía que se extienda, es decir, el miembro protegido seguirá siendo accesible en esta referencia o instancia de clase extendida. Tenga en cuenta que en Class3, si crea una instancia de Class2, no podrá acceder al miembro protegido de Class1 aunque se herede.

Entonces, en resumen, se puede acceder a los miembros protegidos en otros paquetes, solo si alguna clase de este otro paquete, extiende la clase que encierra a este miembro protegido y se accede al miembro protegido en 'esta' referencia o instancias explícitas de clase extendida, dentro de la definición de extendida clase.

public : Este especificador de acceso proporcionará el acceso especificado por el especificador de acceso protegido además del acceso que se describe a continuación.

Cuando está desarrollando algún paquete y, por lo tanto, alguna clase (por ejemplo, Clase1) dentro de él, debe usar un especificador de acceso público para el miembro de datos dentro de Clase1 si desea que este miembro sea accesible en otros paquetes, por ejemplo, en la Clase 1 creada en alguna clase de otra paquete. Básicamente, este especificador de acceso debe usarse cuando intente exponer su miembro de datos al mundo sin ninguna condición.

Tushar Baviskar
fuente