Le principal est-il un identifiant Java valide?

288

Un de mes enfants prend Java au lycée et l'a fait à l'un de ses tests:

Lequel des éléments suivants est un identifiant valide en Java?

une. 123java
b. main
c. java1234
ré. {abce
e. )whoot

Il a répondu b et s'est trompé.

J'ai examiné la question et j'ai fait valoir qu'il main s'agit d' un identifiant valide et qu'il aurait dû être exact.

Nous avons examiné la spécification Java pour les identificateurs et cela a renforcé ce point. Nous avons également écrit un exemple de programme qui avait une variable appelée main, ainsi qu'une méthode. Il a créé une réfutation écrite qui comprenait la référence de la documentation Java, le programme de test et l'enseignant l'a ignoré et dit que la réponse est toujours incorrecte.

Un mainidentifiant est -il valide?

Gary Bak
la source
12
Cela me rend toujours triste de voir un enseignant si peu sûr qu'il / elle a peur d'apprendre quelque chose de nouveau et d'admettre une erreur.
Ryan Lundy
je devine que c'est. mais vous ne devriez vraiment pas l'utiliser comme nom de variable / méthode (malgré le cas évident), donc si l'enseignant essaie de creuser le point pour réfléchir - en particulier dans ce cas - les noms de méthode, je peux voir son / son point.
bharal
3
Cette question demande-t-elle vraiment si l'enseignant de votre fils fait son travail correctement? Je vois deux identificateurs Java valides. La réponse est donc «b» ET «c». Le professeur a donc raison. Ou est-ce que je manque quelque chose?. Comment cela peut-il être une question SO? À en juger par une personne qui ne fait même pas partie de la communauté ...
jschnasse
1
C'est une question sur les enseignants, pas sur java.
ACV du
1
Un autre de ces cas «trompés par votre propre question piège»; les enseignants devraient au moins jeter un coup d'œil aux spécifications linguistiques avant d'essayer de rédiger une question d'examen comme celle-ci.
jrh

Réponses:

253
public class J {
    public static void main(String[] args)
    {
        String main = "The character sequence \"main\" is an identifier, not a keyword or reserved word.";
        System.out.println(main);
    }
}

Ceci compile, et une fois exécuté, émet cette sortie:

The character sequence "main" is an identifier, not a keyword or reserved word.

La séquence de caractères mainest un identifiant, pas un mot-clé ou un mot réservé.

La section pertinente du JLS est 3.8 :

Un identifiant est une séquence de lettres et de chiffres Java de longueur illimitée , dont la première doit être une lettre Java .

Identifiant:

    IdentifierChars mais pas un mot-clé ou BooleanLiteral ou NullLiteral

IdentifierChars:

    JavaLetter {JavaLetterOrDigit}

JavaLetter:

    tout caractère Unicode qui est une "lettre Java"

JavaLetterOrDigit:

    tout caractère Unicode qui est une «lettre ou chiffre Java»

La séquence de caractères maincorrespond à la description ci-dessus et ne figure pas dans la liste de mots - clés de la section 3.9 .

(La séquence de caractères java1234est également un identifiant, pour les mêmes raisons.)

rgettman
la source
25
@Clockwork La question était formulée de telle sorte qu'un seul choix pouvait être correct. Cependant, les deux choix b et c remplissaient la condition de la question, incompatible avec le choix implicite. Cela a laissé l'enfant de l'OP choisir entre la bonne réponse qui était la seule que le professeur pensait correcte.
rgettman
@rgettman J'ai lu " Lequel des énoncés suivants ... " comme autorisant plusieurs choix, auquel " b et c " serait une réponse valide.
TripeHound
6
@TripeHound "est un identifiant valide" est singulier et demande exactement 1 réponse. Comparez-le à "sont des identifiants valides"
Donne
2
Vous auriez pu faire la classe mainaussi;)
Peter Lawrey
97

main est un identifiant java valide et l'enseignant a tort.

La documentation pertinente se trouve dans la spécification du langage Java, ici:

Chapitre 3. "Structure lexicale", section 3.8. "Identifiants":

https://docs.oracle.com/javase/specs/jls/se10/html/jls-3.html#jls-3.8

Ça dit:

Un identifiant est une séquence de lettres et de chiffres Java de longueur illimitée, dont la première doit être une lettre Java ... Un identifiant ne peut pas avoir la même orthographe (séquence de caractères Unicode) qu'un mot clé (§3.9), littéral booléen ( §3.10.3), ou le littéral nul (§3.10.7), ou une erreur de compilation se produit.

Ce qui signifie que vous pouvez prouver qu'il s'agit d'un identifiant valide soit par:

  • le chercher dans la liste des mots-clés java (indice: vous ne le trouverez pas ici!) ou simplement par
  • en l'utilisant comme identifiant et en observant qu'aucune erreur de compilation ne se produit.
Mike Nakis
la source
1
Pourriez-vous citer et expliquer plus explicitement?
zero298
36
non, car c'est une section entière. Si l'enseignant pense que cette section fait une sorte d'exception pour «principal», c'est l'enseignant qui doit montrer où il le dit.
Mike Nakis
76

Comme les autres réponses le disent

mainest un identifiant Java valide , ainsi que java1234.

Je suppose que la confusion vient du fait que la main(String[])méthode est souvent utilisée comme point d'entrée par la JVM 1 . Cependant, cela ne signifie pas que le jeton mainlui-même ne peut pas être utilisé comme identifiant 2 .

Les spécifications le disent et les déclarations suivantes sont également valables:

  • Un champ:

    private int main;
  • Une variable locale:

    String main = "";
  • Une méthode:

    private void main() { ... }
  • Une classe (bien qu'un nom de classe commençant par des minuscules soit déconseillé):

    public class main { ... }
  • Un paquet:

    package main;

1: Comme indiqué dans les commentaires, la spécification JVM elle-même ne prescrit aucune méthode particulière comme point d'entrée, mais l' javaoutil largement utilisé utilise souvent une telle méthode comme point d'entrée.
2: J'éviterais généralement de créer une méthode principale autre que main(String[]).

Empereur MC
la source
22
"Je suppose que la confusion vient du fait que la méthode principale (String []) est utilisée comme point d'entrée pour la JVM." mainn'est pas le point d'entrée de la JVM. C'est le point d'entrée que l' javaoutil utilise pour exécuter des applications. D'autres outils (conteneurs de servlets, par exemple) utilisent d'autres points d'entrée.
TJ Crowder
27
ce qui est encore plus ironique, car même dans le «contexte de point d'entrée» principal, DÉJÀ EST UN identifiant valide. Donc, même le cas contre
lequel
@TJCrowder Merci, j'ai inclus cela dans la réponse.
MC Emperor
1
@Hobbamok Vous semblez confus au sujet des concepts de base de Java, ce qui explique probablement pourquoi vous l'enseignez dans une école et que vous ne pratiquez pas, c'est la réponse qui vient à l'esprit
rath
4
L' javaoutil ne nécessite pas de main(String[])méthode si la classe principale étend javafx.application.Application .
VGR
65

Cela compile très bien sur Java 1.8 ...

public class main {

    public String main = "main"; 

    public void main(String main) {
        System.out.println("This object is an instance of the class " + this.getClass().getCanonicalName());
        System.out.println("The value of the argument \"main\" for this call to the method \"main(String main)\" is " + main);
        System.out.println("The value of the field \"main\" is " + this.main);
    }

    public static void main(String[] args) {
        main main = new main();
        main.main(main.main + main.main);
    }
}

... et une fois exécuté produit la sortie:

This object is an instance of the class main
The value of the argument "main" for this call to the method "main(String main)" is mainmain
The value of the field "main" is main
MichaelK
la source
5
Est-il possible d'ajouter une autre static mainméthode avec des paramètres différents?
jpmc26
6
@ jpmc26 Essayez-le et dites-nous comment cela s'est passé. :)
MichaelK
1
Eh bien, c'est beaucoup de secteur
MC Emperor
4
@MCEmperor Oui, c'est mon principal argument pour ma réponse. ;)
MichaelK
3
Vous avez oublié d'ajouter package main;!
Solomon Ucko
45

J'ai jeté tout ce que j'ai pu dessus, et ça semble marcher. Je dirais que principal est un identifiant valide.

package main;

public class main {

    static main main;
    String Main;

    main(String main) {
        Main = main;
    }

    main(main main) {
        System.out.println(main.Main);
    }

    main main(main main) {
        return new main(main);
    }

    public static void main(main...Main) {
        main:
        for (main main : Main) {
            main = (main instanceof Main) ? new main(main): main.main(main);
            break main;
        }
    }

    public static void main(String[] args) {
        main = new main("main");
        main.main(main, main);
        main = main.new Main(main) {
            main main(main main) {
                return ((Main)main).main();
            }
        };
        main.main(main);
        main.main(main,main);
    }

    abstract class Main extends main {
        Main(main main) {
            super("main");
        }

        main main() {
            main.Main = "Main";
            return main;
        }
    }
}
18107
la source
2
Je l'aime. Essayez un 'grep -o main main.java | wc -l '
Gary Bak
3
Ce code me rappelle un peu le langage de programmation "ook" ^^ Presque chaque mot de ce code est "principal" ...
Florian Bach
public static void main(main...Main)( manque un espace ) ne peut pas fonctionner, n'est-ce pas?
GeroldBroser réintègre Monica le
3
J'ai l'impression de l'avoir souligné.
Ross Presser
1
@GeroldBroser C'est plus propre, mais pas strictement nécessaire: les espaces entre les jetons sont dans de nombreux cas facultatifs, ils ne sont requis que lorsque la concaténation de deux jetons suivants serait sinon également valide.
MC Emperor
44

Comment main ne pas être utilisé comme identifiant alors qu'il est utilisé comme identifiant pour déclarer la méthode "principale"?

Pour un idiome aussi classique:

public class Foo{
   public static void main(String[] args){
   }
}

main n'est pas un mot clé et il ne serait probablement jamais un mot clé en Java pour des raisons évidentes de rétrocompatibilité.


À propos de la question, est main un bon identifiant?

Premièrement: valide pour un compilateur ne signifie pas nécessairement bon.
Par exemple,java1234 option qui est proposée est également un identifiant valide mais cela devrait vraiment être évité.

maina une signification très particulière et importante: elle est utilisée comme méthode de point d'entrée des classes et des jars exécutés par la javaligne de commande.
Utiliser mainpour un nom de méthode qui ne remplit pas les critères à utiliser par la javaligne de commande serait tout simplement trompeur tout en l'utilisant comme nom de variable ou un nom de classe pourrait avoir un sens.
Par exemple, la définition de la classe représentant le point d'entrée d'une application comme Mainclasse de l'application est acceptable et donc son utilisation en tant que nom de variable, comme:

public class Main {

  public static void main(String args[]){
     Main main = new Main();
     // ...
  }      

}

De manière générale, en Java, plusieurs caractères ou "mots" sont considérés comme des identifiants valides pour le compilateur mais sont fortement déconseillés pour être utilisés dans le code client (mais le code généré peut le faire: classes imbriquées par exemple) comme non lisibles et / ou vraiment trompeur.

Par exemple, cela pourrait être valide pour le compilateur:

public class Object { // 1
    public void foo() {
       ...
    }
}

public class BadChosenIdentifier {

    public static void main() { // 2
        new BadChosenIdentifier().toString(new Object());  
    }

    public void toString(Object java1234) { // 3, 4
        String _result$ = java1234 + " -> to avoid"; // 4
        System.out.println(_result$);
    }    
}

Mais nous ne voulons pas:

  • pour nommer Objectnotre classe comme cela est défini dans java.lang(1).
  • pour nommer une méthode main()si ne remplit pas les critères à utiliser par la javaligne de commande (2).
  • pour surcharger la Object.toString()méthode (3).
  • pour nommer nos variables _, $ou tout caractère surprenant / sans signification qui va à l'encontre des conventions de nommage partagées (4).
davidxxx
la source
7
Juste pour noter, mainpourrait être un mot-clé qui ne peut être utilisé que comme nom pour une méthode statique avec une signature appropriée (ou autre). Notez que les appels de super classe utilisent superd'une manière qui le fait ressembler à un identifiant: super(foo);et super.foo, mais superEST un mot-clé (et avant l'ajout de génériques, c'était la seule façon de l'utiliser (dont je me souviens)).
jaxad0127
@ jaxad0127 Point intéressant mais je ne suis pas tout à fait d'accord. En fait, ce n'est PAS le cas et à l'avenir, cela ne pourrait probablement pas l'être pour des raisons de compatibilité. Si vous avez défini mainun mot-clé dans une nouvelle version de java, cela signifie que tout code qui utilise main comme nom de méthode (ou tout nom de membre) ne sera plus compilé. L'utilisation de supergénériques n'a aucun effet secondaire dans le code existant car les génériques n'existaient pas à ce moment.
davidxxx
2
Je voulais juste dire que cela aurait pu être fait en tant que mot clé. Ce n'est pas parce qu'il ressemble à un identifiant qu'il doit l'être.
jaxad0127
2
Je dirais que mainc'est toujours un meilleur identifiant que java1234. L'utiliser pour une méthode "régulière" serait trompeur, mais je n'aurais aucun problème à nommer une variable main, si c'est en fait le principal élément de ma méthode. java1234est tout simplement horrible, les noms devraient être descriptifs ...
AJPerez
1
"A propos de la question, est-ce que principal est un bon identifiant?" Ça dépend. Je ne serais probablement pas attentif à une variable nommée mainsi la fonction que je regardais faisait quelque chose avec les données principales de l'eau. Je vomirais si jamais je voyais java1234du code de production (et je prie pour qu'il n'y ait pas 1233 autres variables avec le préfixe java).
jpmc26
40

Est-ce un identifiant valide? Oui.

Est-ce un bon identifiant? Pas si vous l'utilisez pour autre chose que la méthode qui démarre au lancement de la JVM.

Un autre identifiant valide est-il répertorié? Oui.

Les instructions du test indiquaient-elles de choisir la meilleure réponse?

user1423956
la source
7
D'accord - le choix multiple comme celui-ci consiste à choisir la «meilleure» bonne réponse lorsqu'il y en a plusieurs. Cependant, cela ne fait pas de cette question une bonne question à choix multiples et je pense qu'en parler à l'enseignant est la bonne chose à faire.
Shadow
19
@Shadow Il s'agit d'un cours de programmation. L'ambiguïté sur une question concernant quelque chose qui est spécifié avec la grammaire mathématique formelle est intolérable. S'exprimant strictement contre cette norme (ce qui est impliqué par « valide »), les deux réponses sont également correctes. Je peux imaginer beaucoup plus de cas dans lesquels mainest un identifiant tolérable que je ne java1234pourrais l'être. Considérons, par exemple, une base de code fonctionnant avec des données d'alimentation en eau (conduites d'eau).
jpmc26
5
D'un autre côté, java1234 pue vers le haut des cieux comme identifiant.
Joshua
4
"Choisir la meilleure réponse" ne signifie pas "comprendre quand l'enseignant ne sait pas de quoi il parle et deviner la mauvaise réponse à laquelle il pense." main n'est pas seulement un identifiant valide , c'est un identifiant très important car chaque application Java a une méthode principale, et les méthodes sont nommées avec des identifiants.
fluffysheap
2
Je trouve cette réponse très appréciée et j'aimerais pouvoir la voter plus d'une fois. Il semble que vous essayez de prendre parti à tout prix et que vous ne considérez pas la situation dans son ensemble. mainest un identifiant parfaitement fin n'importe où en dehors du domaine étroit de l'application Java standard. Il peut s'agir du nom d'un champ d'une classe représentant un menu fixe. Ou une <main>section d'un document dans un générateur HTML. java1234, d'autre part, est à peu près aussi terrible que les identifiants.
toniedzwiedz
29

mainest parfaitement valide car, d' après les documents :

  1. Est une "séquence de lettres Java et de chiffres Java, dont la première est une lettre Java"
  2. N'est pas un mot - clé
  3. N'est pas un littéral booléen c'est-à-dire "vrai" ou "faux"
  4. N'est pas littéral nul
zero298
la source
29
public class Main {
    private static String main;
    public static void main(String[] main) {
        Main.main = main[0];
        new Main().main(Main.main);
    }
    private void main(String main) {
        System.out.println(main);
    }
}
ililit
la source
7

L'enseignant a commis une erreur mineure en supposant que main n'est pas un identifiant valide ou en formulant simplement la question de manière erronée. Il voulait peut-être dire "un bon identifiant".
Mais ignorer les arguments de votre fils et décourager ainsi son approche scientifique de vérification de la littérature pertinente (spécification Java) et de réalisation d'une expérience (écriture d'un exemple de programme) est exactement le contraire de ce qu'un enseignant est censé faire.

user82593
la source
1
Comme indiqué dans d'autres réponses, mainest beaucoup plus souvent un «bon» identificateur que ce java1234ne serait le cas. Alors même là, l'enseignant a tort. ;)
jpmc26
5

Les deux mainet java123sont valides des identificateurs, principal n'est pas un mot - clé réservé de sorte qu'il est parfaitement acceptable d'utiliser, pour autant que le test va vous devez avoir obtenu un point ou un demi - point au moins.

shavar
la source
5
  1. Doit être un seul mot. Autrement dit, les espaces ne sont pas autorisés.

    Exemple: mangoprice est valide mais le prix de la mangue n'est pas valide.

  2. Doit commencer par une lettre (alphabet) ou un trait de soulignement ou $.

    Exemple: prix, _ prix et $ prix sont des identifiants valides.

  3. Ne doit pas être un mot clé de Java car le mot clé a une signification particulière pour le compilateur.

    Exemple: classe ou vide, etc.

  4. Ne doit pas commencer par un chiffre mais le chiffre peut être au milieu ou à la fin.

    Exemple: 5mangoescost n'est pas valide et mango5cost et mangocost5 sont valides.

  5. La longueur d'un identifiant en Java peut être de 65 535 caractères et tous sont significatifs. Les identificateurs sont sensibles à la casse. Cela signifie que la mangue et la mangue sont traitées différemment. Peut contenir toutes les lettres majuscules ou minuscules ou un mélange.

IDENTIFICATEUR : ce sont des noms de classe, des noms de méthode, des noms de variables ...

Comme principal n'est pas un mot réservé et selon l'explication ci-dessus pour définir un identifiant, principal est un identifiant valide et java1234 également.Les options restantes ne sont pas valides en raison de l'explication ci-dessus.

subhashis
la source