Pourquoi Java nous permet-il de compiler une classe avec un nom différent du nom de fichier?

170

J'ai un fichier Test.javaet le code suivant à l'intérieur.

public class Abcd
{
        //some code here

}

Maintenant, la classe ne compile pas, mais quand je supprime le publicmodificateur, elle se compile correctement.

Quel est le raisonnement derrière Java qui nous permet de compiler un nom de classe différent du nom de fichier lorsqu'il n'est pas public.

Je sais que c'est une question pour les débutants, mais je ne suis pas en mesure de trouver une bonne explication.

user2434
la source
28
Parce que Java. (Parce que ce n'est pas public et qu'il n'est pas nécessaire de suivre la même convention de dénomination. Au-delà de cela, vous devrez demander aux gens qui l'ont inventé.)
Dave Newton
2
Je doute qu'il y ait une "bonne explication". C'était une exigence pour les classes publiques, mais elle était jugée inutile pour les classes non publiques.
Kayaman
2
On dirait une question similaire: stackoverflow.com/questions/7633631/…
sanket
4
Pourquoi tant de votes positifs pour cette question, tout d'abord sa question en double: stackoverflow.com/questions/7633631/…
GM Ramesh
2
@ Ramesh: le titre et le contenu de cette question sont meilleurs .. (que les autres similaires)
Jayan

Réponses:

325

Le raisonnement est d'autoriser plus d'une classe de premier niveau par .javafichier.

De nombreuses classes, telles que les écouteurs d'événements, sont à usage local uniquement et les premières versions de Java ne prenaient pas en charge les classes imbriquées. Sans cet assouplissement de la règle "nom de fichier = nom de classe", chacune de ces classes aurait eu besoin de son propre fichier, avec le résultat inévitable d'une prolifération sans fin de petits .javafichiers et de la dispersion d'un code étroitement couplé.

Dès que Java a introduit les classes imbriquées, l'importance de cette règle a considérablement diminué. Aujourd'hui, vous pouvez parcourir plusieurs centaines de fichiers Java, sans jamais en trouver un qui en profite.

Marko Topolnik
la source
60
+1, cela fournit en fait une raison , qui est la question.
Dave Newton
4
+1 pour les informations historiques en particulier - je soupçonne qu'avec l'avènement des classes imbriquées / anonymes, si la même décision devait être prise maintenant (sans se soucier de la compatibilité descendante), il serait beaucoup plus logique de n'autoriser qu'une seule classe de haut niveau par fichier.
Michael Berry
1
@ berry120 Très probablement, car cette allocation complique la recherche de fichiers lors de la compilation.
Marko Topolnik
3
@Val Refuser que d'autres personnes préfèrent utiliser un éditeur de texte et des outils CLI pour développer parce que l'IDE que vous préférez existe est tout aussi ridicule que de dire qu'il est inutile de créer des IDE car vous pouvez faire du développement sans eux. Les deux approches sont utilisées par de bons développeurs pour créer un code de qualité; et la seule chose plus petite que les chances de tous les développeurs de régler l'un d'entre eux et de chanter kumbaya est la probabilité que nous soyons tous d'accord sur le meilleur langage de programmation.
Dan Is Fiddling By Firelight
5
La combinaison d'Emacs (ou Vim, choisissez votre poison) et les utilitaires shell Unix ne sont peut-être pas aussi tout à portée de main qu'un IDE moderne, et ils sont certainement plus difficiles à apprendre, mais ils ont deux avantages écrasants par rapport à tous les IDE que j'ai jamais essayés: ils ne plantent jamais, quelle que soit la taille de la base de code, et ils peuvent suivre ma frappe.
zwol
80

La raison est la même que pour les plaques de porte. Si une personne réside officiellement dans le bureau (déclaré public), son nom doit figurer sur l'étiquette de porte. Comme "Alex Jones" ou "Detective Colombo". Si quelqu'un visite simplement la pièce, parle à un fonctionnaire ou nettoie le sol, son nom n'a pas à être officiellement inscrit sur la porte. Au lieu de cela, la porte peut lire «Utilitaires» ou «Salle de réunion».

Nom officiel ou MyClass.java Salle de réunion ou Test.java

exebook
la source
4
Certainement une analogie intéressante; il pourrait être encore mieux avec un peu d'explication sur la façon dont cela se rapporte directement. L'OP pourrait avoir des difficultés à établir la connexion (bien que je le comprenne parfaitement)
Andrew Barber
4
@AndrewBarber Je ne pense pas que l'analogie convient vraiment car elle ne modélise pas la classe publique unique, partageant le fichier avec plusieurs classes privées de package. C'est comme la plaque de porte qui lisait "Heather Santee, Manager", mais la pièce contenant en fait Heather et ses deux secrétaires.
Marko Topolnik
@MarkoTopolnik Je n'aurais pas dû m'impliquer là-dedans; Je suis de classe A horrible aux analogies! ;)
Andrew Barber
@AndrewBarber Je voulais l'écrire, de toute façon; vous venez de donner un coup de pouce :) L'analogie ne parvient pas non plus à exprimer la préoccupation la plus aiguë: juste à cause de cette fonctionnalité, le compilateur doit analyser tous les fichiers pour découvrir toutes les classes, sinon il pourrait simplement lire la liste des répertoires et connaître les noms de tous classes de haut niveau.
Marko Topolnik
@AndrewBarber, l'analogie correspond parfaitement à l'idée de répertoire, dans le long couloir, vous pouvez rapidement trouver une personne en regardant simplement les plaques de porte, vous n'avez pas besoin d'entrer dans chaque pièce et de demander.
exebook
29

La spécification Java stipule que vous ne pouvez avoir au plus qu'une classe publique par fichier. Dans ce cas, le nom de la classe doit correspondre au nom du fichier. Toutes les classes non publiques sont autorisées à avoir n'importe quel nom, quel que soit le nom du fichier.

Andrei Nicusan
la source
20
Mais "quel est le raisonnement derrière Java permettant" cela?
Marko Topolnik
@MarkoTopolnik Parce que ça ne nous empêche pas: D
Maroun
8
@MarounMaroun Mais quel est le raisonnement derrière ne pas nous empêcher?
Marko Topolnik
@Marko Java permet d'avoir plusieurs classes définies dans le même fichier (tant qu'une seule d'entre elles est publique). Comme toutes les classes d'un même package doivent avoir un nom différent, il n'y a pas d'autre option que d'autoriser les classes non publiques à avoir un nom autre que le nom de fichier.
isnot2bad
2
Mes 2 centimes: peut-être qu'il a été conçu de cette façon pour une localisation plus rapide des classes dans classpath. Avec cette convention, l'inspection des noms de fichiers / chemins est suffisante pour la découverte de classe. Sans cette convention, le chargeur de classe classpath pourrait avoir besoin d'ouvrir et d'analyser des fichiers afin de trouver des classes
Andrei Nicusan
13

Je pense que les autoriser est une condition préalable aux classes imbriquées. Les classes anonymes en particulier réduisent considérablement le nombre de fichiers .java requis. Sans support pour cela, vous auriez besoin de beaucoup d'implémentations d'interface de méthode unique dans leurs propres fichiers séparés de la classe principale dans laquelle ils sont utilisés (je pense aux écouteurs d'action en particulier)

Il y a une bonne explication de toutes les classes imbriquées dans le didacticiel Java sur les classes imbriquées sur le site Web d'Oracle, qui contient des exemples de chacune. Cela a également une raison pour laquelle ils sont utiles, que je vais citer:

Pourquoi utiliser des classes imbriquées?

Les raisons impérieuses d'utiliser des classes imbriquées sont les suivantes:

  • C'est une façon de regrouper logiquement des classes qui ne sont utilisées qu'à un seul endroit : si une classe n'est utile qu'à une seule autre classe, alors il est logique de l'intégrer dans cette classe et de garder les deux ensemble. L'imbrication de ces «classes d'assistance» rend leur package plus simple.

  • Cela augmente l'encapsulation : considérez deux classes de niveau supérieur, A et B, où B a besoin d'accéder aux membres de A qui seraient autrement déclarés privés. En masquant la classe B dans la classe A, les membres de A peuvent être déclarés privés et B peut y accéder. De plus, B lui-même peut être caché du monde extérieur.

  • Cela peut conduire à un code plus lisible et maintenable : l'imbrication de petites classes dans des classes de niveau supérieur rapproche le code de l'endroit où il est utilisé.

(c'est moi qui souligne)

Je ne suis pas familier avec les spécifications Java à l'époque, mais une recherche rapide montre que des classes internes ont été ajoutées dans Java 1.1.

Joshua McKinnon
la source
Que doit-on faire dans les cas où un type n'est utile que dans un autre type, mais les instances du premier type ne sont pas associées aux instances du second?
supercat du
Les classes imbriquées sont la façon Java 1.2 de faire des lambdas ou des «fonctions de première classe lorsque tout est un objet». Cela change dans la syntaxe 1.8. Ils sont également utilisés lorsque nous voulons modéliser des types de données algébriques dans le système Type de Java.
hawkeye
12

Je regarde les choses dans l'autre sens. L'état naturel des choses serait que le programmeur choisisse à la fois le nom de la classe et le nom du fichier indépendamment. Probablement afin de simplifier la recherche de classes publiques depuis l'extérieur d'un package lors de la compilation, il existe une restriction spéciale selon laquelle une classe publique se trouve dans un fichier avec le nom correspondant.

Patricia Shanahan
la source
4

Notez que Java est sensible à la casse, mais que le système de fichiers n'a pas besoin de l'être. Si le nom de base du fichier est "abcd", mais que la classe est "Abcd", cela serait-il conforme à la règle sur un système de fichiers insensible à la casse? Certainement pas lorsqu'il est porté sur un système sensible à la casse.

Ou supposons que vous ayez une classe appelée ABCD, et une classe Abcd (ne pensons pas que ce soit une mauvaise idée: cela pourrait arriver) et que le programme soit porté sur un système de fichiers insensible à la casse. Maintenant, vous devez non seulement renommer les fichiers, mais aussi les classes, oups!

Ou que faire s'il n'y a pas de fichier? Supposons que vous ayez un compilateur Java qui peut prendre une entrée sur une entrée standard. Alors la classe doit être nommée "StandardInput"?

Si vous explorez rationnellement les implications d'exiger que les noms de fichiers suivent les noms de classe, vous constaterez que c'est une mauvaise idée à plus d'un titre.

Kaz
la source
Je suis d'accord avec ce que vous avez à dire, mais je ne sais pas si cela répond particulièrement à la question, sauf peut-être dans la mesure où certains des problèmes résultant de l'architecture de nommage pourraient être atténués en permettant aux noms de classes non publics d'être différents de noms de fichiers. BTW, en ce qui concerne la casse, si je dérivez une langue, dans tous les contextes ont Fooété déclarés, les identifiants FOO, foo, fOo, etc. seraient tous « non défini » , même si elles existaient dans les champs extérieurs. Une telle conception éliminerait le problème de la sensibilité à la casse pour les noms de fichiers.
supercat du
3

Un autre point que beaucoup de réponses ont manqué de souligner est que sans la publicdéclaration, la JVM ne saurait jamais quelle méthode principale de classes doit être appelée. Toutes les classes déclarées dans un fichier .java peuvent toutes avoir des méthodes principales, mais la méthode principale n'est exécutée que sur la classe marquée comme publique. HTH

happybuddha
la source
0

Étant donné qu'un fichier java peut contenir plus d'une classe, il peut avoir deux classes dans un seul fichier java. Mais un fichier java doit contenir une classe portant le même nom que le nom de fichier s'il contient une classe publique.

podongfeng
la source
Non, cette règle n'est applicable que pour les classes publiques.
deadboy