¿Por qué Java nos permite compilar una clase con un nombre diferente al nombre del archivo?

170

Tengo un archivo Test.javay el siguiente código dentro.

public class Abcd
{
        //some code here

}

Ahora la clase no se compila, pero cuando elimino el publicmodificador, se compila bien.

¿Cuál es el razonamiento detrás de Java que nos permite compilar un nombre de clase que es diferente del nombre del archivo cuando no es público?

Sé que es una pregunta para novatos, pero no puedo encontrar una buena explicación.

usuario2434
fuente
28
Porque Java (Debido a que no es público y no tiene que seguir la misma convención de nomenclatura. Más allá de eso, deberá preguntarle a la gente que lo inventó)
Dave Newton
2
Dudo que haya una "buena explicación". Era un requisito para las clases públicas, pero se consideró innecesario para las clases no públicas.
Kayaman
2
Parece una pregunta similar: stackoverflow.com/questions/7633631/…
sanket
44
¿Por qué tantos votos a favor para esta pregunta, en primer lugar su pregunta duplicada: stackoverflow.com/questions/7633631/…
GM Ramesh
2
@ Ramesh: el título y el contenido de esta pregunta es mejor ... (que los otros similares)
Jayan

Respuestas:

325

La razón es permitir más de una clase de nivel superior por .javaarchivo.

Muchas clases, como los oyentes de eventos, son solo de uso local y las primeras versiones de Java no admitían clases anidadas. Sin esta relajación de la regla "nombre de archivo = nombre de clase", todas y cada una de esas clases habrían requerido su propio archivo, con el resultado inevitable de la proliferación interminable de .javaarchivos pequeños y la dispersión de código estrechamente acoplado.

Tan pronto como Java introdujo clases anidadas, la importancia de esta regla disminuyó significativamente. Hoy en día puede revisar cientos de archivos Java, sin cambiar nunca uno que lo aproveche.

Marko Topolnik
fuente
6060
+1, esto realmente proporciona una razón , que es la pregunta.
Dave Newton el
44
+1 para la información histórica especialmente: sospecho que con el advenimiento de clases anidadas / anónimas, si se tomara la misma decisión ahora (sin importar la compatibilidad con versiones anteriores), tendría mucho más sentido permitir solo una clase de nivel superior por expediente.
Michael Berry
1
@ berry120 Muy probablemente, porque esta asignación complica la búsqueda de archivos al compilar.
Marko Topolnik el
3
@Val Negar que otras personas prefieran usar un editor de texto y herramientas de CLI para desarrollar porque el IDE que prefieres existe es tan tonto como decir que no tiene sentido crear IDEs porque puedes desarrollar sin ellos. Ambos enfoques son utilizados por buenos desarrolladores para crear código de calidad; y lo único más pequeño que las probabilidades de que todos los desarrolladores resuelvan uno de ellos y canten kumbaya es la probabilidad de que todos estemos de acuerdo en cuál es el mejor lenguaje de programación.
Dan está tocando el violín el
55
La combinación de Emacs (o Vim, elige tu veneno) y las utilidades de shell de Unix quizás no sean tan accesibles como un IDE moderno, y ciertamente son más difíciles de aprender, pero tienen dos ventajas abrumadoras en comparación con todos los IDE que he probado: nunca se bloquean, no importa cuán grande sea la base de código, y pueden seguir el ritmo de mi escritura.
zwol
80

La razón es la misma que para las placas de la puerta. Si alguna persona reside oficialmente en la oficina (declarada pública), su nombre debe estar en la etiqueta de la puerta. Como "Alex Jones" o "Detective Colombo". Si alguien visita la sala, habla con un funcionario o limpia el piso, su nombre no tiene que ponerse oficialmente en la puerta. En cambio, la puerta puede leer "Utilidades" o "Sala de reuniones".

Nombre oficial o MyClass.java Sala de reuniones o Test.java

exebook
fuente
44
Definitivamente una analogía interesante; podría ser aún mejor con un poco de explicación de cómo se relaciona directamente. El OP podría tener algunas dificultades para hacer la conexión (aunque lo entiendo perfectamente)
Andrew Barber
44
@ AndrewBarber No creo que la analogía realmente se ajuste, ya que no modela la única clase pública, compartiendo el archivo con varias clases privadas de paquetes. Es como la placa de la puerta que dice "Heather Santee, Gerente", pero la habitación en realidad contiene a Heather y sus dos secretarias.
Marko Topolnik
@MarkoTopolnik No debería haberme involucrado en esto; ¡Soy de clase A horrible en analogías! ;)
Andrew Barber
@ AndrewBarber Quería escribirlo, de todos modos; acabas de dar un empujón :) La analogía tampoco expresa la preocupación más aguda: solo debido a esta característica, el compilador debe analizar todos los archivos para descubrir todas las clases, de lo contrario, simplemente podría leer la lista del directorio y conocer los nombres de todos clases de alto nivel.
Marko Topolnik
@AndrewBarber, la analogía se adapta perfectamente a la idea de directorio, en el largo pasillo puedes encontrar rápidamente a una persona simplemente mirando las placas de la puerta, no es necesario que entres a cada habitación y preguntes.
exebook
29

La especificación Java establece que solo puede tener como máximo una clase pública por archivo. En este caso, el nombre de la clase debe coincidir con el nombre del archivo. Todas las clases no públicas pueden tener cualquier nombre, independientemente del nombre del archivo.

Andrei Nicusan
fuente
20
Pero "¿cuál es el razonamiento detrás de Java que nos permite" esto?
Marko Topolnik el
@MarkoTopolnik Porque no nos impide: D
Maroun
8
@MarounMaroun Pero, ¿cuál es el razonamiento detrás de no impedirnos?
Marko Topolnik el
@Marko Java permite tener múltiples clases definidas en el mismo archivo (siempre que solo una de ellas sea pública). Como todas las clases dentro del mismo paquete deben tener un nombre diferente, no hay otra opción que permitir que las clases no públicas tengan un nombre que no sea el nombre del archivo.
isnot2bad
2
Mis 2 centavos: tal vez fue diseñado de esta manera para una localización más rápida de las clases dentro de classpath. Con esta convención, inspeccionar los nombres / rutas de los archivos es suficiente para el descubrimiento de clases. Sin esta convención, el cargador de clases classpath podría necesitar abrir y analizar archivos para encontrar clases
Andrei Nicusan
13

Creo que permitirlos es un requisito previo para las clases anidadas. Las clases anónimas, en particular, reducen drásticamente la cantidad de archivos .java necesarios. Sin soporte para esto, necesitaría muchas implementaciones de interfaz de método único en sus propios archivos separados de la clase principal en la que se utilizan. (Estoy pensando en los oyentes de acción en particular)

Hay una buena explicación de todas las clases anidadas en el tutorial Java Clases anidadas en el sitio web de Oracle, que tiene ejemplos de cada una. También tiene una razón por la que son útiles, que citaré:

¿Por qué usar clases anidadas?

Las razones convincentes para usar clases anidadas incluyen las siguientes:

  • Es una forma de agrupar lógicamente clases que solo se usan en un lugar : si una clase es útil solo para otra clase, entonces es lógico integrarla en esa clase y mantener las dos juntas. Anidar tales "clases auxiliares" hace que su paquete sea más ágil.

  • Aumenta la encapsulación : considere dos clases de nivel superior, A y B, donde B necesita acceso a los miembros de A que de otro modo se declararían privados. Al ocultar la clase B dentro de la clase A, los miembros de A pueden declararse privados y B puede acceder a ellos. Además, B se puede ocultar del mundo exterior.

  • Puede conducir a un código más fácil de leer y mantener : anidar clases pequeñas dentro de las clases de nivel superior coloca el código más cerca de donde se usa.

(énfasis mío)

No estoy familiarizado con las especificaciones de Java en los primeros días, pero una búsqueda rápida muestra que se agregaron clases internas en Java 1.1.

Joshua McKinnon
fuente
¿Qué se debe hacer en los casos en que un tipo solo es útil dentro de otro tipo, pero las instancias del primer tipo no están asociadas con instancias del segundo?
supercat
Las clases anidadas son la forma Java 1.2 de hacer lambdas o 'Funciones de primera clase cuando todo es un objeto'. Esto está cambiando en la sintaxis 1.8. También se usan cuando queremos modelar tipos de datos algebraicos en el sistema de tipos de Java.
Hawkeye
12

Lo miro al revés. El estado natural de las cosas sería que el programador elija el nombre de la clase y el nombre del archivo de forma independiente. Probablemente para simplificar la búsqueda de clases públicas desde fuera de un paquete durante la compilación, existe una restricción especial de que una clase pública esté en un archivo con el nombre correspondiente.

Patricia Shanahan
fuente
4

Tenga en cuenta que Java distingue entre mayúsculas y minúsculas, pero el sistema de archivos no necesita serlo. Si el nombre base del archivo es "abcd", pero la clase es "Abcd", ¿se ajustaría a la regla en un sistema de archivos que no distingue entre mayúsculas y minúsculas? Ciertamente no cuando se transfiere a mayúsculas y minúsculas.

O supongamos que tiene una clase llamada ABCD, y una clase Abcd (no pensemos que es una mala idea: podría suceder) y el programa se transfiere a un sistema de archivos que no distingue entre mayúsculas y minúsculas. Ahora no solo tiene que cambiar el nombre de los archivos, sino también las clases, ¡vaya!

¿O qué pasa si no hay un archivo? Supongamos que tiene un compilador de Java que puede tomar datos de entrada estándar. Entonces, ¿la clase debe llamarse "StandardInput"?

Si explora racionalmente las implicaciones de requerir que los nombres de archivo sigan a los nombres de clase, encontrará que es una mala idea en más de una forma.

Kaz
fuente
Estoy de acuerdo con lo que tiene que decir, pero no sé si responde particularmente a la pregunta, excepto quizás en la medida en que algunos de los problemas resultantes de la arquitectura de nombres podrían aliviarse al permitir que los nombres de clase no públicos sean diferentes de nombres de archivo Por cierto, con respecto a mayúsculas y minúsculas, si obtenían un idioma, en cualquier ámbito se Foofue declarada, los identificadores FOO, foo, fOo, etc todos serían "indefinido", incluso si existieran dentro de los alcances exteriores. Tal diseño eliminaría el problema de mayúsculas y minúsculas para los nombres de archivo.
supercat
3

También otro punto que muchas respuestas omitieron señalar es que sin la publicdeclaración, la JVM nunca sabría qué método principal de las clases debe invocarse. Todas las clases declaradas en un archivo .java pueden tener métodos principales, pero el método principal se ejecuta solo en la clase marcada como pública. HTH

happybuddha
fuente
0

Debido a que un archivo java puede contener más de una clase, puede tener dos clases en un archivo java. Pero un archivo Java debe contener una clase con el mismo nombre que el archivo si contiene una clase pública.

podongfeng
fuente
No, esa regla solo es aplicable para las clases públicas.
deadboy