Ist main eine gültige Java-Kennung?

288

Eines meiner Kinder nimmt Java in der High School und hatte dies bei einem seiner Tests:

Welcher der folgenden Bezeichner ist in Java gültig?

ein. 123java
b. main
c. java1234
d. {abce
e. )whoot

Er antwortete b und verstand es falsch.

Ich schaute auf die Frage und argumentiert , dass main ist ein gültiger Bezeichner und dass es richtig sein sollte.

Wir haben uns die Java- Spezifikation für Bezeichner angesehen und sie hat diesen Punkt verstärkt. Wir haben auch ein Beispielprogramm geschrieben, das eine Variable namens mainsowie eine Methode hatte. Er erstellte eine schriftliche Gegenargumentation, die die Java-Dokumentationsreferenz enthielt, das Testprogramm und der Lehrer ignorierte sie und sagte, die Antwort sei immer noch falsch.

Ist maineine gültige Kennung?

Gary Bak
quelle
12
Es macht mich immer traurig, einen Lehrer so unsicher zu sehen, dass er Angst hat, etwas Neues zu lernen und einen Fehler zuzugeben.
Ryan Lundy
Ich denke es ist. Aber Sie sollten es wirklich nicht als Variablen- / Methodennamen verwenden (ungeachtet des offensichtlichen Falls). Wenn der Lehrer also versucht, den Punkt nach Hause zu bohren, um über Methodennamen nachzudenken - insbesondere in diesem Fall -, kann ich seine / sehen ihr Punkt.
Bharal
3
Stellt sich diese Frage wirklich, ob der Lehrer Ihres Sohnes seine Arbeit richtig macht? Ich sehe zwei gültige Java-Bezeichner. Die Antwort lautet also 'b' UND 'c'. Der Lehrer hat also Recht. Oder fehlt mir etwas? Wie kann das eine SO-Frage sein? Nach einer Person zu urteilen, die nicht einmal Teil der Gemeinschaft ist ...
jschnasse
1
Dies ist eine Frage zu Lehrern, nicht zu Java.
ACV
1
Ein anderer dieser Fälle, die "von Ihrer eigenen Trickfrage ausgetrickst" wurden; Lehrer sollten sich zumindest die Sprachspezifikation ansehen, bevor sie versuchen, eine solche Prüfungsfrage zu schreiben.
jrh

Antworten:

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);
    }
}

Dies kompiliert und gibt bei Ausführung diese Ausgabe aus:

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

Die Zeichenfolge mainist eine Kennung, kein Schlüsselwort oder reserviertes Wort.

Der relevante Abschnitt des JLS ist 3.8 :

Ein Bezeichner ist eine unbegrenzte Folge von Java-Buchstaben und Java-Ziffern , von denen der erste ein Java-Buchstabe sein muss .

Kennung:

    IdentifierChars, aber kein Schlüsselwort oder BooleanLiteral oder NullLiteral

IdentifierChars:

    JavaLetter {JavaLetterOrDigit}

JavaLetter:

    jedes Unicode-Zeichen, das ein "Java-Buchstabe" ist

JavaLetterOrDigit:

    jedes Unicode-Zeichen, das ein "Java-Buchstabe oder eine Ziffer" ist

Die Zeichenfolge entspricht mainder obigen Beschreibung und ist nicht in der Schlüsselwortliste in Abschnitt 3.9 enthalten .

(Die Zeichenfolge java1234ist aus den gleichen Gründen auch eine Kennung.)

rgettman
quelle
25
@Clockwork Die Frage wurde so formuliert, dass nur eine Auswahl richtig sein konnte. Beide Auswahlmöglichkeiten b und c erfüllten jedoch die Bedingung der Frage, was nicht mit der implizierten Auswahl übereinstimmt. Dies ließ das Kind des OP wählen, welche richtige Antwort die einzige war, die der Lehrer für richtig hielt.
Rgettman
@rgettman Ich habe " Welche der folgenden ... " gelesen, um mehr als eine Auswahl zu ermöglichen, auf die " b und c " eine gültige Antwort wäre.
TripeHound
6
@TripeHound "ist eine gültige Kennung" ist singulär und erfordert genau 1 Antwort. Vergleichen Sie es mit "sind gültige Bezeichner"
Gimme den 411
2
Du main
hättest auch
97

main ist eine gültige Java-Kennung und der Lehrer ist falsch.

Die entsprechende Dokumentation finden Sie in der Java-Sprachspezifikation hier:

Kapitel 3. "Lexikalische Struktur", Abschnitt 3.8. "Kennungen":

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

Es sagt:

Ein Bezeichner ist eine Folge von Java-Buchstaben und Java-Ziffern mit unbegrenzter Länge, von denen der erste ein Java-Buchstabe sein muss ... Ein Bezeichner kann nicht dieselbe Schreibweise (Unicode-Zeichenfolge) haben wie ein Schlüsselwort (§3.9), ein Boolesches Literal ( §3.10.3) oder das Nullliteral (§3.10.7) oder ein Fehler bei der Kompilierung tritt auf.

Dies bedeutet, dass Sie nachweisen können, dass es sich um eine gültige Kennung handelt, indem Sie:

  • Suchen Sie danach in der Liste der Java-Schlüsselwörter (Hinweis: Sie werden es dort nicht finden!) oder einfach nach
  • Verwenden Sie es als Kennung und stellen Sie fest, dass kein Fehler bei der Kompilierung auftritt.
Mike Nakis
quelle
1
Könnten Sie es genauer zitieren und formulieren?
Null298
36
nein, weil es ein ganzer abschnitt ist. Wenn der Lehrer der Meinung ist, dass dieser Abschnitt eine Ausnahme für 'main' macht, muss der Lehrer zeigen, wo er dies sagt.
Mike Nakis
76

Wie die anderen Antworten sagen

mainist eine gültige Java-Kennung sowie java1234.

Ich denke, die Verwirrung kommt von der Tatsache, dass die main(String[])Methode oft als Einstiegspunkt von der JVM 1 verwendet wird . Dies bedeutet jedoch nicht, dass das Token mainselbst nicht als Bezeichner 2 verwendet werden kann .

Die Spezifikationen sagen dies, und die folgenden Erklärungen sind ebenfalls gültig:

  • Ein Feld:

    private int main;
  • Eine lokale Variable:

    String main = "";
  • Eine Methode:

    private void main() { ... }
  • Eine Klasse (obwohl von einem Klassennamen, der mit Kleinbuchstaben beginnt, abgeraten wird):

    public class main { ... }
  • Ein Packet:

    package main;

1: Wie in den Kommentaren erwähnt, schreibt die JVM-Spezifikation selbst keine bestimmte Methode als Einstiegspunkt vor, aber das weit verbreitete javaTool verwendet häufig eine solche Methode als Einstiegspunkt.
2: Ich würde im Allgemeinen vermeiden, eine andere Hauptmethode als zu erstellen main(String[]).

MC Kaiser
quelle
22
"Ich denke, die Verwirrung kommt von der Tatsache, dass die Hauptmethode (String []) als Einstiegspunkt für die JVM verwendet wird." mainist nicht der Einstiegspunkt für die JVM. Dies ist der Einstiegspunkt, über den das javaTool Anwendungen ausführt. Andere Tools (z. B. Servlet-Container) verwenden andere Einstiegspunkte.
TJ Crowder
27
Das ist noch ironischer, denn selbst im "Einstiegspunkt-Kontext" ist main BEREITS eine gültige Kennung. Selbst der Fall, den Sie dagegen halten könnten, beweist OP-Recht
Hobbamok
@TJCrowder Danke, das habe ich in die Antwort aufgenommen.
MC Emperor
1
@Hobbamok Sie scheinen verwirrt über grundlegende Java - Konzepte, die wohl erklärt , warum Sie es in einer Schule unterrichten und nicht zu praktizieren ist die Antwort , die in den Sinn kommt
rath
4
Das javaTool benötigt keine main(String[])Methode, wenn die Hauptklasse javafx.application.Application erweitert .
VGR
65

Dies kompiliert gut auf 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);
    }
}

... und bei Ausführung wird die Ausgabe erzeugt:

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
quelle
5
Ist es möglich, eine andere static mainMethode mit anderen Parametern hinzuzufügen ?
jpmc26
6
@ jpmc26 Probieren Sie es aus und erzählen Sie uns, wie es gelaufen ist. :)
MichaelK
1
Nun , das ist eine Menge Netz
MC Emperor
4
@MCEmperor Ja, das ist mein Hauptargument für meine Antwort. ;)
MichaelK
3
Du hast vergessen hinzuzufügen package main;!
Solomon Ucko
45

Ich warf alles, was ich konnte, und es scheint zu funktionieren. Ich würde sagen, main ist eine gültige Kennung.

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
quelle
2
Ich mag das. Versuchen Sie es mit 'grep -o main main.java | wc -l '
Gary Bak
3
Dieser Code erinnert mich irgendwie an die Programmiersprache "ook" ^^ Fast jedes Wort in diesem Code ist "main" ...
Florian Bach
public static void main(main...Main)( fehlt ein Leerzeichen ) kann nicht funktionieren, oder?
GeroldBroser stellt Monica
3
Ich habe das Gefühl, ich habe es gepflegt.
Ross Presser
1
@GeroldBroser Das ist sauberer, aber nicht unbedingt erforderlich: Leerzeichen zwischen Token sind in vielen Fällen optional. Sie sind nur erforderlich, wenn ansonsten auch die Verkettung von zwei nachfolgenden Token gültig wäre.
MC Emperor
44

Wie main es nicht als Bezeichner verwendet werden, während es als Bezeichner zum Deklarieren der "Haupt" -Methode verwendet wird?

Für solch eine klassische Sprache:

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

main ist kein Schlüsselwort und würde aus offensichtlichen Gründen der Retro-Kompatibilität wahrscheinlich nie ein Schlüsselwort in Java sein.


Über die Frage ist main eine gute Kennung?

Erstens: Gültig für einen Compiler bedeutet nicht unbedingt gut.
Zum Beispiel diejava1234 ist die vorgeschlagene Option auch eine gültige Kennung, aber das sollte wirklich vermieden werden.

mainhat eine ganz besondere und wichtige Bedeutung: Sie wird als Einstiegspunktmethode für Klassen und Jars verwendet, die von der javaBefehlszeile ausgeführt werden .
Die Verwendung maineines Methodennamens, der die von der javaBefehlszeile zu verwendenden Kriterien nicht erfüllt, wäre nur irreführend, wenn er als Variablenname oder Klassenname verwendet wird.
Beispielsweise Mainist es akzeptabel , die Klasse, die den Einstiegspunkt einer Anwendung darstellt, als Klasse der Anwendung zu definieren und sie daher auch als Variablennamen zu verwenden, z.

public class Main {

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

}

Im Allgemeinen werden in Java mehrere Zeichen oder "Wörter" als gültige Bezeichner für den Compiler betrachtet, es wird jedoch dringend davon abgeraten, sie im Client-Code zu verwenden (generierter Code kann dies jedoch tun: verschachtelte Klassen zum Beispiel) als nicht lesbar und / oder wirklich irreführend.

Dies könnte beispielsweise für den Compiler gültig sein:

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$);
    }    
}

Aber wir wollen nicht:

  • um Objectunsere Klasse so zu benennen , wie dies in java.lang(1) definiert ist.
  • um eine Methode zu benennen, main()wenn die von der javaBefehlszeile zu verwendenden Kriterien nicht erfüllt sind (2).
  • um die Object.toString()Methode (3) zu überladen .
  • unsere Variablen mit nennen _, $oder bei einem der überraschenden / unmeaningful Zeichen , die gegen die gemeinsamen Benennungskonventionen gehen (4).
davidxxx
quelle
7
Nur zu beachten, mainkönnte ein Schlüsselwort sein, das nur als Name für eine statische Methode mit einer geeigneten Signatur (oder was auch immer) verwendet werden kann. Beachten Sie, dass Super-Class-Aufrufe so verwendet superwerden, dass sie wie ein Bezeichner aussehen: super(foo);und super.foo, aber superIS ein Schlüsselwort (und bevor Generika hinzugefügt wurden, war dies die einzige Möglichkeit, sie zu verwenden (an die ich mich erinnern kann)).
jaxad0127
@ jaxad0127 Interessanter Punkt, aber ich stimme nicht ganz zu. Eigentlich ist es nicht und in Zukunft könnte es wahrscheinlich aus Gründen der Kompatibilität noch nicht sein. Wenn Sie mainin einer neuen Java-Version als Schlüsselwort definiert haben , bedeutet dies, dass Code, der main als Methodennamen (oder Mitgliedsnamen) verwendet, nicht mehr kompiliert wird. Die Verwendung von superin Generika hat keine Nebenwirkungen in vorhandenem Code, da zu diesem Zeitpunkt keine Generika vorhanden waren.
Davidxxx
2
Ich meinte nur, dass es als Schlüsselwort hätte getan werden können. Nur weil es wie ein Bezeichner aussieht, heißt das nicht, dass es sein muss.
jaxad0127
2
Ich würde argumentieren, dass dies mainimmer noch eine bessere Kennung ist als java1234. Es wäre irreführend, es für eine "normale" Methode zu verwenden, aber ich hätte kein Problem damit, eine Variable zu benennen main, wenn es tatsächlich das wichtigste Element in meiner Methode ist. java1234ist einfach schrecklich, Namen sollten beschreibend sein ...
AJPerez
1
"Über die Frage, ist main eine gute Kennung?" Es hängt davon ab, ob. Ich würde wahrscheinlich kein Auge auf eine Variable namens werfen, mainwenn die Funktion, die ich betrachtete, etwas mit Wasserhauptdaten zu tun hätte. Ich würde kotzen , wenn ich jemals sah java1234in der Produktion Code (und beten dort nicht 1233 andere Variablen mit dem Präfix waren java).
jpmc26
40

Ist es eine gültige Kennung? Ja.

Ist es eine gute Kennung? Nicht, wenn Sie es für etwas anderes als die Methode verwenden, die beim Start von JVM beginnt.

Ist eine andere gültige Kennung aufgeführt? Ja.

Haben die Testanweisungen gesagt, um die beste Antwort zu wählen?

user1423956
quelle
7
Einverstanden - Bei Multiple Choice wie dieser geht es darum, die 'beste' richtige Antwort zu wählen, wenn es mehrere gibt. Dies macht dies jedoch nicht zu einer guten Multiple-Choice-Frage, und ich denke, dass es richtig ist, mit dem Lehrer darüber zu sprechen.
Schatten
19
@Shadow Dies ist ein Programmierkurs. Unklarheiten bei einer Frage zu etwas, das mit formaler mathematischer Grammatik spezifiziert ist, sind unerträglich. Beide Antworten sprechen gleichermaßen gegen diesen Standard (was durch " gültig " impliziert wird ) und sind gleichermaßen richtig. Ich kann mir weit mehr Fälle vorstellen, in denen maineine tolerierbare Kennung vorliegt, als ich kann java1234. Stellen Sie sich zum Beispiel eine Codebasis vor, die mit Wasserversorgungsdaten (Wasserleitungen) arbeitet.
jpmc26
5
Auf der anderen Seite stinkt Java1234 als Identifikator in den Himmel.
Joshua
4
"Wähle die beste Antwort" bedeutet nicht "Finde heraus, wenn der Lehrer nicht weiß, wovon er spricht, und rate die schlechte Antwort, an die er denkt." main ist nicht nur ein gültiger Bezeichner, sondern auch ein sehr wichtiger Bezeichner, da jede Java-Anwendung über eine Hauptmethode verfügt und Methoden mit Bezeichnern benannt werden.
Fluffysheap
2
Ich finde diese Antwort sehr einfühlsam und wünschte, ich könnte sie mehr als einmal ablehnen. Es scheint, dass Sie versuchen, um jeden Preis eine Seite zu vertreten, ohne das Gesamtbild zu berücksichtigen. mainist eine vollkommen feine Kennung außerhalb der engen Domäne einer einfachen Java-Anwendung. Dies kann der Name eines Feldes in einer Klasse sein, das ein festgelegtes Menü darstellt. Oder ein <main>Abschnitt eines Dokuments in einem HTML-Builder. java1234Auf der anderen Seite ist es ungefähr so ​​schrecklich, wie Identifikatoren es bekommen.
toniedzwiedz
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
quelle
7

Dieser Lehrer hat einen kleinen Fehler gemacht, indem er entweder angenommen hat, dass main keine gültige Kennung ist, oder einfach die Frage falsch formuliert hat. Er wollte möglicherweise "eine gute Kennung" sagen.
Das Ignorieren der Argumente Ihrer Söhne und damit das Entmutigen seines wissenschaftlichen Ansatzes, relevante Literatur (Java-Spezifikation) zu überprüfen und ein Experiment durchzuführen (Schreiben eines Beispielprogramms), ist das genaue Gegenteil von dem, was ein Lehrer tun soll.

user82593
quelle
1
Wie in anderen Antworten erwähnt, mainist es viel häufiger eine "gute" Kennung als es java1234wäre. Selbst dort liegt der Lehrer falsch. ;)
jpmc26
5

Beide mainund java123sind gültige Bezeichner. Main ist kein reserviertes Schlüsselwort, daher ist es durchaus akzeptabel, es zu verwenden. Nach dem Test sollten Sie mindestens einen oder einen halben Punkt erreicht haben.

Shavar
quelle
5
  1. Sollte ein einzelnes Wort sein. Das heißt, Leerzeichen sind nicht erlaubt.

    Beispiel: Mangopreis ist gültig, aber der Mangopreis ist nicht gültig.

  2. Sollte mit einem Buchstaben (Alphabet) oder einem Unterstrich oder einem $ -Symbol beginnen.

    Beispiel: Preis, _Preis und $ Preis sind gültige Bezeichner.

  3. Sollte kein Schlüsselwort von Java sein, da das Schlüsselwort für den Compiler eine besondere Bedeutung hat.

    Beispiel: Klasse oder nichtig usw.

  4. Sollte nicht mit einer Ziffer beginnen, sondern kann in der Mitte oder am Ende stehen.

    Beispiel: 5mangoescost ist ungültig und mango5cost und mangocost5 sind gültig.

  5. Die Länge eines Bezeichners in Java kann 65.535 Zeichen betragen und alle sind von Bedeutung. Bezeichner unterscheiden zwischen Groß- und Kleinschreibung. Das heißt, Mango und Mango werden unterschiedlich behandelt. Kann alle Groß- oder Kleinbuchstaben oder eine Mischung enthalten.

IDENTIFIER : Dies sind Klassennamen, Methodennamen, Variablennamen ...

Da main kein reserviertes Wort ist und gemäß der obigen Erklärung zum Definieren eines Bezeichners main ein gültiger Bezeichner und java1234 auch ist. Die verbleibenden Optionen sind aufgrund der obigen Erklärung nicht gültig.

Subhashis
quelle