¿Cuál es la diferencia entre público, protegido, paquete privado y privado en Java?




que es public en programacion (20)

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.

Predeterminado: Es accesible en el mismo paquete desde cualquiera de la clase de paquete.

Para acceder puedes 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 el objeto de la clase secundaria.

Privado: se puede acceder en la misma clase.

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

En Java, ¿existen reglas claras sobre cuándo usar cada uno de los modificadores de acceso, es decir, el predeterminado (paquete privado), public , protected y private , al tiempo que se crea una class e interface y se trata de la herencia?


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 a las subclases de la clase en la que se declara al 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 usando la referencia de la clase principal. ....


Muchas veces me he dado cuenta de que recordar los conceptos básicos de cualquier lenguaje puede ser posible mediante la creación de analogías del mundo real. Aquí está mi analogía para entender 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 ven tú y tu amigo es esta estatua. Esto significa que cualquier persona que camina en el campus puede mirar la estatua sin el permiso de la universidad. Esto hace que la estatua sea PÚBLICA .

  • A continuación, desea llevar a su amigo a su dormitorio, pero para eso necesita registrarlo como visitante. Esto significa que recibe 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 como PROTEGIDA .

  • Tu 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 sean PRIVADAS .

¡Espero que esto ayude!


La diferencia se puede encontrar en los enlaces que ya se proporcionaron, pero cuál usar usualmente se reduce al "Principio del conocimiento mínimo". Solo permita la menor visibilidad que se necesite.


El tutorial oficial puede ser de alguna utilidad para usted.

            │ Class │ Package │ Subclass │ Subclass │ World
            │       │         │(same pkg)│(diff pkg)│ 
────────────┼───────┼─────────┼──────────┼──────────┼────────
public      │   +   │    +    │    +     │     +    │   +     
────────────┼───────┼─────────┼──────────┼──────────┼────────
protected   │   +   │    +    │    +     │     +    │         
────────────┼───────┼─────────┼──────────┼──────────┼────────
no modifier │   +   │    +    │    +     │          │    
────────────┼───────┼─────────┼──────────┼──────────┼────────
private     │   +   │         │          │          │    

+ : accessible
blank : not accessible

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 de una clase en otra, se producirá 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 para las clases en el mismo paquete y para 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


En muy corto

  • public : accesible desde todas partes.
  • 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 dentro de la misma clase solamente.

Privado

  • Métodos, variables y constructores.

Los métodos, variables y constructores que se declaran privados solo pueden accederse 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 de obtención públicos están presentes en la clase. Solo las subclases de otro paquete o cualquier clase dentro del paquete de la clase de los miembros protegidos pueden acceder a las variables, métodos y constructores declarados protegidos en una superclase.

Protegido

  • Clase e interfaz

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

Los métodos, 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 o variable auxiliar, mientras evita que una clase no relacionada intente usarlo.

Público

Se puede acceder a una clase, método, constructor, interfaz, etc. declarada pública 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, la clase pública aún debe ser importada.

Debido a la herencia de clase, todos los métodos y variables públicos 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 final estático y los métodos en una interfaz son públicos por defecto.

Nota

No podemos anular los campos estáticos. Si intenta anularlo, no se muestra ningún error, pero no funciona con lo que nosotros 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


Como una regla de oro:

  • privado : alcance de la clase.
  • predeterminado (o paquete-privado ): alcance del paquete.
  • protected : package scope + child (como package, pero podemos crear subclases de diferentes paquetes). El modificador protegido siempre mantiene la relación "padre-hijo".
  • Público : 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).
  • (R) eference (invocar un método utilizando una referencia a la clase, o mediante la sintaxis de "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   |
+—————————————————+————————————+———————————+

Aquí hay una mejor versión de la tabla. (Prueba de futuro con una columna para módulos).

Explicaciones

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

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

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

  • Un miembro público es accesible a todas las clases (a menos que resida en un module que no exporte el paquete en el que está declarado).

¿Qué modificador elegir?

Los modificadores de acceso son una herramienta para ayudarlo a prevenir la ruptura accidental de la encapsulación (*) . Pregúntese si desea que el miembro sea algo que sea interno a la clase, paquete, jerarquía de clases o que no sea interno en absoluto, y elija el nivel de acceso en consecuencia.

Ejemplos:

  • Es probable que un campo long internalCounter sea ​​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.
  • Un método interno void beforeRender() llamado justo antes de renderizar y usado como un gancho en subclases debe estar protegido.
  • Un void saveGame(File dst) que se void saveGame(File dst) desde el código GUI debe ser público.

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


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

Privado

Como pensaría, solo la clase en la que está declarado puede verlo.

Paquete privado

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

Protegido

El paquete Privado + puede ser visto por subclases o miembro del paquete.

Público

Todos pueden verlo.

Published

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 sepa, mejor.

¿Cuándo deberías usar qué? Toda la idea es encapsulación para ocultar información. En la medida de lo posible, desea ocultar los detalles de cómo se hace algo a 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é utilizando el código que acaba de revisar.

Por lo tanto, la regla de oro es hacer las cosas 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 sea absolutamente necesario para 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 internos para que puedan anularlos, a menudo es una mejor idea meter esas agallas en un objeto y hacer que la interfaz sea pública. De esa manera, simplemente pueden enchufar un nuevo objeto. Por ejemplo, si estuviera escribiendo un reproductor de CD y quisiera que el bit de "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 el objeto que obtiene / establece. . De esta manera, ser tacaño al exponer sus entrañas fomenta la buena composición y la separación de preocupaciones

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

Aquí es donde entra la idea de "publicado". Cambiar una interfaz (refactorizarla) requiere que encuentre todo el código que lo está utilizando y que también lo cambie. Si la interfaz es privada, bueno no hay problema. Si está protegido tienes que ir a buscar todas tus subclases. Si es público tienes que buscar todo el código que usa tu código. A veces esto es posible, por ejemplo, si está trabajando en un código corporativo que es solo para uso interno, no importa si una interfaz es pública. Puedes tomar 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 se encuentra en una página. Debe soportar esa interfaz o código de riesgo de ruptura. Incluso las interfaces protegidas se pueden considerar publicadas (por lo que no me molesto en protegerlas).

Muchos idiomas consideran 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 está el concepto de una clase de rasgo , pero ese es otro espectáculo.


La respuesta de David proporciona el significado de cada modificador de acceso. En cuanto a cuándo usar cada una, 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, sabrá cuándo hacer que algunas clases sean privadas para el paquete y cuándo declarar ciertos métodos protegidos para su uso en subclases.


El modificador de acceso más incomprendido en Java está 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 esperamos clarifique la confusión:

  • Supongamos que tenemos 2 clases; Father e 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() al 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 se define foo() ( 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 this o 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 principal y está dentro del paquete donde se define foo() ( 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 principal y está fuera del paquete donde se define foo() ( 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 no subclases):

      package sonpackage;
      
      public class SomeClass
      {
          public void someMethod(Son s) throws Exception
          {
              s.foo(); // compilation error
          }
      }
      

Privado : acceso limitado a la clase solamente

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

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

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


                | 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         |       ✔       |     ✘     |       ✘       |   ✘    

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

Esto está relacionado con los modificadores de acceso de Java .

Desde los modificadores de acceso de Java :

Un modificador de acceso de 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 de Java también se denominan a veces en el discurso diario como especificadores de acceso de Java, pero el nombre correcto es modificadores de acceso de Java. Las clases, campos, constructores y métodos pueden tener uno de los cuatro modificadores de acceso Java diferentes:

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

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

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 privado de paquetes (sin modificador explícito).

Una clase puede ser declarada con el modificador public, en cuyo caso esa clase es visible para todas las clases en cualquier lugar. Si una clase no tiene modificador (el valor predeterminado, también conocido como paquete-privado), es visible solo 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 en sí tiene acceso al miembro definido por el nivel de acceso. Como puedes 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 parentesco) 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.


  • Público - accesible desde cualquier lugar en la aplicación.

  • por defecto - accesible desde el paquete.

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

  • Privado - accesible solo desde su clase.


Solo quiero abordar un detalle que generalmente se equivoca, incluida la mayoría de las respuestas en esta página. El acceso "predeterminado" (cuando no hay un modificador de acceso presente) no es siempre el mismo que el paquete privado . Depende de lo que sea la cosa.

  • Los tipos no miembros (es decir, clases, enumeraciones, interfaces y tipos de anotación no declarados dentro de otro tipo) son paquetes privados por defecto. ( JLS §6.6.1 )

  • Los miembros de la clase y los constructores son paquetes privados por defecto. ( JLS §6.6.1 )

  • Los constructores de enumeración son privados por defecto . (De hecho, los proveedores de enumeración deben ser privados, y es un error tratar de hacerlos públicos o protegidos). Las constantes de enumeración son públicas y no permiten ningún especificador de acceso. Otros miembros de enums son paquete-privados por defecto. ( JLS §8.9 )

  • Todos los miembros de interfaces y tipos de anotación son públicos por defecto . (De hecho, los miembros de interfaces y tipos de anotación deben ser públicos, y es un error tratar de hacerlos privados o protegidos.) ( JLS §9.3 a 9.5 )


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

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

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

Por ejemplo: puede colocar métodos de seguridad confidenciales en un paquete de 'seguridad'. Luego ponga una clase pública que acceda a parte del código relacionado con la seguridad en este paquete, pero mantenga el paquete de otras clases de seguridad en privado . 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 una de la otra pueden terminar en el mismo paquete y eventualmente podrían ser refactorizadas o fusionadas si la dependencia es demasiado fuerte.

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


Regla fácil. Comience con declarar todo lo privado. Y luego el progreso hacia el público a medida que surgen las necesidades y el diseño lo justifica.

Al exponer a los miembros, pregúntese si está exponiendo las opciones de representación o las opciones de abstracción. Lo 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 los métodos abstractos protegidos si desea que se invalide.

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





access-modifiers