¿Cuál es el especificador de acceso predeterminado en Java?

108

Empecé a leer un libro de Java y me pregunté; ¿Qué especificador de acceso es el predeterminado, si no se especifica ninguno?

Bennedich
fuente
El término correcto es "modificador de acceso". La palabra "especificador" no aparece en el JLS.
Marqués de Lorne

Respuestas:

116

La visibilidad predeterminada se conoce como "paquete-privado" (aunque no se puede usar explícitamente), lo que significa que se podrá acceder al campo desde el interior del mismo paquete al que pertenece la clase.

Sin embargo, como señaló mdma, no es cierto para los miembros de la interfaz, para los cuales el valor predeterminado es "público".

Ver los especificadores de acceso de Java

KeatsPeeks
fuente
25
incorrecto: no es cierto para los miembros de la interfaz. el acceso predeterminado es público
mdma
2
En realidad, se lo conoce como "paquete privado". Los sitios web de terceros no son referencias normativas. Debería citar solo el JLS.
Marqués de Lorne
81

El especificador predeterminado depende del contexto.

Para clases y declaraciones de interfaz, el paquete predeterminado es privado. Esto cae entre protegido y privado, permitiendo solo el acceso de clases en el mismo paquete. (protected es así, pero también permite el acceso a subclases fuera del paquete).

class MyClass   // package private
{
   int field;    // package private field

   void calc() {  // package private method

   }
}

Para los miembros de la interfaz (campos y métodos), el acceso predeterminado es público. Pero tenga en cuenta que la declaración de la interfaz en sí misma tiene como valor predeterminado el paquete privado.

interface MyInterface  // package private
{
   int field1;         // static final public

   void method1();     // public abstract
}

Si entonces tenemos la declaración

public interface MyInterface2 extends MyInterface
{

}

Las clases que usan MyInterface2 pueden ver field1 y method1 desde la superinterfaz, porque son públicas, aunque no pueden ver la declaración de MyInterface en sí.

mdma
fuente
1
"Paquete privado" (a veces escrito en fuente como /* pp */) es solo un nombre conveniente para el acceso predeterminado . No es el nombre de JLS.
Tom Hawtin - tackline
10
@Tom - eso es correcto, el JLS usa "acceso predeterminado". Podría haber escrito "el acceso predeterminado es el predeterminado". ¡Pero eso no pareció muy útil!
mdma
16

Si no se proporciona un especificador de acceso, es acceso a nivel de paquete (no hay un especificador explícito para esto) para clases y miembros de clase. Los métodos de interfaz son implícitamente públicos.

Michael Borgwardt
fuente
9

La visibilidad predeterminada (sin palabra clave) es paquete, lo que significa que estará disponible para todas las clases ubicadas en el mismo paquete.

Una nota al margen interesante es que protected no limita la visibilidad a las subclases sino también a las otras clases en el mismo paquete

Johannes Wachter
fuente
8

Depende de lo que sea.

  • Los tipos de nivel superior (es decir, clases, enumeraciones, interfaces y tipos de anotaciones no declarados dentro de otro tipo) son paquetes privados de forma predeterminada. ( JLS §6.6.1 )

  • En las clases, todos los miembros (es decir, campos, métodos y declaraciones de tipos anidados) y constructores son paquetes privados de forma predeterminada. ( JLS §6.6.1 )

    • Cuando una clase no tiene un constructor declarado explícitamente, el compilador inserta un constructor de argumento cero predeterminado que tiene el mismo especificador de acceso que la clase . ( JLS §8.8.9 ) El constructor predeterminado comúnmente se declara erróneamente como siempre público, pero en casos raros eso no es equivalente.
  • En las enumeraciones, los constructores son privados de forma predeterminada. De hecho, los constructores de enumeración deben ser privados, y es un error especificarlos como públicos o protegidos. Las constantes de enumeración son siempre públicas y no permiten ningún especificador de acceso. Otros miembros de enumeraciones son paquetes privados de forma predeterminada. ( JLS §8.9 )

  • En interfaces y tipos de anotaciones, todos los miembros (nuevamente, eso significa campos, métodos y declaraciones de tipos anidados) son públicos por defecto. De hecho, los miembros de las interfaces y los tipos de anotaciones deben ser públicos y es un error especificarlos como privados o protegidos. ( JLS §9.3 a 9.5 )

  • Las clases locales son clases con nombre declaradas dentro de un método, constructor o bloque inicializador. Tienen un alcance en el bloque {.. }en el que se declaran y no permiten ningún especificador de acceso. ( JLS §14.3 ) Con la reflexión, puede crear instancias de clases locales desde otros lugares, y son paquetes privados , aunque no estoy seguro de si ese detalle está en JLS.

  • Las clases anónimas son clases personalizadas creadas con las newque se especifica un cuerpo de clase directamente en la expresión. ( JLS §15.9.5 ) Su sintaxis no permite ningún especificador de acceso. Con la reflexión, puede crear instancias de clases anónimas desde otros lugares, y tanto ellas como sus constructores generados son paquetes privados , aunque no estoy seguro de si ese detalle está en el JLS.

  • Los bloques de inicializador estático y de instancia no tienen especificadores de acceso a nivel de idioma ( JLS §8.6 y 8.7 ), pero los bloques de inicializador estático se implementan como un método denominado <clinit>( JVMS §2.9 ), por lo que el método debe, internamente, tener algún especificador de acceso. Examiné clases compiladas por javac y por el compilador de Eclipse usando un editor hexadecimal y descubrí que ambos generan el método como paquete privado . Sin embargo, no puede llamar <clinit>()dentro del idioma porque los caracteres <y >no son válidos en el nombre de un método, y los métodos de reflexión están programados para negar su existencia, por lo que efectivamente su especificador de acceso es sin acceso . El método solo puede ser llamado por la máquina virtual, durante la inicialización de la clase.Los bloques inicializadores de instancias no se compilan como métodos separados; su código se copia en cada constructor, por lo que no se puede acceder a ellos individualmente, incluso por reflexión.

Boann
fuente
7

default es una palabra clave que se utiliza como modificador de acceso para métodos y variables.
El uso de este modificador de acceso hará que su clase, variable, método o constructor sea accesible desde su propia clase o paquete, y también se establecerá si no hay ningún modificador de acceso presente.

  Access Levels
    Modifier    Class   Package Subclass  EveryWhere
    public        Y        Y       Y         Y
    protected     Y        Y       Y         N
    default       Y        Y       N         N
    private       Y        N       N         N

si usa un valor predeterminado en una interfaz, podrá implementar un método como este ejemplo

public interface Computer {    
    default void Start() {
        throw new UnsupportedOperationException("Error");
    }    
}

Sin embargo, solo funcionará desde la versión 8 de Java

Documentación oficial

Modificadores de acceso en Java

Amadeu Antunes
fuente
3

Consulte aquí para obtener más detalles. El valor predeterminado no es privado / público / protegido, sino una especificación de acceso completamente diferente. No se usa mucho y prefiero ser mucho más específico en mis definiciones de acceso.

Brian Agnew
fuente
3

el especificador de acceso predeterminado es paquete. Las clases pueden acceder a los miembros de otras clases en el mismo paquete. pero fuera del paquete aparece como privado

abhi
fuente
3

Aquí hay una cita sobre la visibilidad a nivel de paquete de una entrevista con James Gosling, el creador de Java:

Bill Venners : Java tiene cuatro niveles de acceso. El valor predeterminado es paquete. Siempre me he preguntado si hacer que el acceso al paquete sea predeterminado era conveniente porque las tres palabras clave que la gente de C ++ ya conocía eran privadas, protegidas y públicas. O si tenía alguna razón en particular por la que pensaba que el acceso al paquete debería ser el predeterminado.

James Gosling : Un paquete es generalmente un conjunto de cosas que se escriben juntas. De manera genérica, podría haber hecho una de dos cosas. Una era obligarte a poner siempre una palabra clave que te diera el dominio. O podría haber tenido un valor predeterminado. Y luego la pregunta es, ¿qué hace un valor predeterminado razonable? Y suelo apostar por lo menos peligroso.

Así que public hubiera sido algo realmente malo hacer el valor predeterminado. Privado probablemente hubiera sido algo malo establecer un valor predeterminado, aunque solo sea porque la gente en realidad no escribe métodos privados con tanta frecuencia. Y lo mismo con protegido. Y al mirar un montón de código que tenía, decidí que lo más común que era razonablemente seguro estaba en el paquete. Y C ++ no tenía una palabra clave para eso, porque no tenían una noción de paquetes.

Pero me gustó más que la noción de amigos, porque con los amigos tienes que enumerar quiénes son todos tus amigos, por lo que si agregas una nueva clase a un paquete, generalmente terminas teniendo que ir a todos los clases en ese paquete y actualizar a sus amigos, lo que siempre me pareció un completo dolor de cabeza.

Pero la lista de amigos en sí misma causa una especie de problema de versiones. Y entonces existía esta noción de una clase amigable. Y lo bueno es que lo estaba convirtiendo en el predeterminado: resolveré el problema, entonces, ¿cuál debería ser la palabra clave?

Durante un tiempo hubo una palabra clave amigable. Pero debido a que todos los demás comienzan con "P", fue "amistoso" con un "PH". Pero eso solo estuvo allí tal vez por un día.

http://www.artima.com/intv/gosling2P.html

Vitalii Fedorenko
fuente
2

Actualizar el uso de palabras clave de Java 8default : como muchos otros han notado La visibilidad predeterminada (sin palabra clave)

el campo será accesible desde dentro del mismo paquete al que pertenece la clase.

No debe confundirse con la nueva característica de Java 8 ( métodos predeterminados ) que permite que una interfaz proporcione una implementación cuando está etiquetada con la defaultpalabra clave.

Ver: modificadores de acceso

Ahmad Sanie
fuente
-2

En primer lugar, déjeme decir una cosa: no existe un término como "Especificador de acceso" en Java. Deberíamos llamar a todo como "Modificadores". Como sabemos que final, estático, sincronizado, volátil ... se llaman modificadores, incluso Público, privado, protegido, predeterminado, abstracto también deben llamarse como modificadores. El valor predeterminado es un modificador en el que la existencia física no existe pero no se coloca ningún modificador, entonces debe tratarse como modificadores predeterminados.

Para justificar esto, tome un ejemplo:

public class Simple{  
    public static void main(String args[]){  
     System.out.println("Hello Java");  
    }  
}  

La salida será: Hello Java

Ahora cambie de público a privado y vea qué error del compilador obtiene: Dice "El modificador privado no está permitido aquí". La conclusión es que alguien puede estar equivocado o algún tutorial puede estar equivocado, pero el compilador no puede estar equivocado. Entonces, podemos decir que no hay un especificador de acceso a términos en Java, todo son modificadores.

Sagar Raut
fuente
La primera oración es acertada, pero el hecho de que una clase externa no pueda ser privada no prueba que no exista un especificador de acceso en Java.
Marqués de Lorne
@EJP Esto es solo un ejemplo. Lo que estoy diciendo es que el término especificador de acceso se usa en otros lenguajes como c, dot net, etc. pero el término técnico en Java para esto es modificadores. Si usa eclipse o cualquier otro IDE, puede ver que en el momento de crear una nueva clase se nos pide que proporcionemos el nombre de los modificadores y en la lista proporcionan público, privado, abstracto, etc.
Sagar Raut
En mi ejemplo, lo que trato de decir es que el compilador da un mensaje de error: los modificadores privados no están permitidos, no dan un mensaje como el especificador de acceso privado no permitido. Entonces, el término técnico que deberíamos decir es modificadores en java, no especificador de acceso en java
Sagar Raut