Czy główny jest prawidłowym identyfikatorem Java?

288

Jedno z moich dzieci bierze Javę w szkole średniej i miało to na jednym ze swoich testów:

Który z poniższych elementów jest prawidłowym identyfikatorem w Javie?

za. 123java
b. main
do. java1234
re. {abce
mi. )whoot

Odpowiedział b i pomylił się.

Spojrzałem na pytanie i argumentowałem, że main jest to prawidłowy identyfikator i że powinien był mieć rację.

Przyjrzeliśmy się specyfikacji Java dla identyfikatorów i to wzmocniło ten punkt. Napisaliśmy również przykładowy program, który miał zmienną o nazwie main, a także metodę. Stworzył pisemne obalenie, które zawierało odniesienie do dokumentacji Java, program testowy i nauczyciel zignorowali go i stwierdzili, że odpowiedź jest nadal nieprawidłowa.

Czy mainprawidłowy identyfikator?

Gary Bak
źródło
12
Zawsze bardzo mi przykro, że nauczyciel jest tak niepewny, że boi się nauczyć czegoś nowego i przyznać się do błędu.
Ryan Lundy,
Myślę, że to jest. ale tak naprawdę nie powinieneś używać go jako nazwy zmiennej / metody (bez względu na oczywisty przypadek), więc jeśli nauczyciel próbuje wytropić punkt, w którym należy się zastanowić - szczególnie w tym przypadku - nazwy metod, to mogę zobaczyć jego / jej punkt.
bharal
3
Czy to pytanie naprawdę nasuwa, czy nauczyciel twojego syna prawidłowo wykonuje swoją pracę? Widzę dwa prawidłowe identyfikatory Java. Tak więc odpowiedź brzmi „b” ORAZ „c”. Więc nauczyciel ma rację. A może coś mi brakuje? Jak to może być pytanie SO? Sądząc o osobie, która nawet nie należy do społeczności ...
jschnasse,
1
To pytanie dotyczy nauczycieli, a nie javy.
ACV
1
Kolejny z przypadków „oszukanych przez twoje własne pytanie”; nauczyciele naprawdę powinni przynajmniej rzucić okiem na specyfikę języka przed próbą napisania takiego pytania egzaminacyjnego.
jrh

Odpowiedzi:

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

To kompiluje, a po uruchomieniu emituje następujące dane wyjściowe:

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

Sekwencja znaków mainjest identyfikatorem, a nie słowem kluczowym ani słowem zastrzeżonym.

Istotne odcinek JLS 3.8 :

identyfikator jest sekwencją nieograniczonej długości liter Java i cyfr w języku Java , z których pierwszy musi być literą Java .

Identyfikator:

    IdentifierChars, ale nie słowo kluczowe, BooleanLiteral lub NullLiteral

Identyfikator:

    JavaLetter {JavaLetterOrDigit}

JavaLetter:

    dowolny znak Unicode będący „literą Java”

JavaLetterOrDigit:

    dowolny znak Unicode, który jest „literą lub cyfrą Java”

Sekwencja znaków mainpasuje do powyższego opisu i nie znajduje się na liście słów kluczowych w Rozdziale 3.9 .

(Sekwencja znaków java1234jest również identyfikatorem, z tych samych powodów.)

rgettman
źródło
25
@Clockwork Pytanie zostało sformułowane w taki sposób, że tylko jeden wybór może być prawidłowy. Jednak obie opcje b i c spełniały warunek pytania, co jest niezgodne z wyborem domyślnym. Dzięki temu dziecko PO mogło wybrać, która poprawna odpowiedź była jedyną, którą nauczyciel uznał za prawidłową.
rgettman
@rgettman Przeczytałem „ Które z poniższych ... ”, pozwalając na więcej niż jeden wybór, na które „ b i c ” byłyby prawidłową odpowiedzią.
TripeHound,
6
@TripeHound „jest ważnym identyfikatorem” jest liczbą pojedynczą i wymaga dokładnie 1 odpowiedzi. Porównaj to z „są ważnymi identyfikatorami”
daj 411
2
Mógłbyś także wziąć udział w zajęciach main;)
Peter Lawrey
97

main jest prawidłowym identyfikatorem Java, a nauczyciel się myli.

Odpowiednia dokumentacja znajduje się w specyfikacji języka Java, tutaj:

Rozdział 3. „Struktura leksykalna”, sekcja 3.8. „Identyfikatory”:

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

To mówi:

Identyfikator jest sekwencją liter Java i cyfr Java o nieograniczonej długości, z których pierwsza musi być literą Java ... Identyfikator nie może mieć takiej samej pisowni (sekwencji znaków Unicode) jak słowo kluczowe (§3.9), literał logiczny ( §3.10.3) lub literału zerowego (§3.10.7) lub występuje błąd kompilacji.

Co oznacza, że ​​możesz udowodnić, że jest to prawidłowy identyfikator poprzez:

  • szukając go na liście słów kluczowych java (wskazówka: nie znajdziesz go tam!) lub po prostu przez
  • użycie go jako identyfikatora i zauważenie, że nie wystąpił błąd czasu kompilacji.
Mike Nakis
źródło
1
Czy możesz zacytować i przeliterować to bardziej precyzyjnie?
zero298,
36
nie, ponieważ jest to cała sekcja. Jeśli nauczyciel uważa, że ​​ten rozdział stanowi wyjątek dla „głównego”, to nauczyciel musi pokazać, gdzie to mówi.
Mike Nakis,
76

Jak podają inne odpowiedzi

mainjest poprawnym identyfikatorem Java , a także java1234.

Myślę, że zamieszanie wynika z faktu, że main(String[])JVM 1 często stosuje tę metodę jako punkt wejścia . Nie oznacza to jednak, że mainsam token nie może być używany jako identyfikator 2 .

Specyfikacja tak mówi i obowiązują również następujące deklaracje:

  • Pole:

    private int main;
  • Zmienna lokalna:

    String main = "";
  • Metoda:

    private void main() { ... }
  • Klasa (chociaż nazwa klasy zaczynająca się od małych liter jest odradzana):

    public class main { ... }
  • Paczka:

    package main;

1: Jak zauważono w komentarzach, sama specyfikacja JVM nie nakazuje żadnej konkretnej metody jako punktu wejścia, ale powszechnie używane javanarzędzie często stosuje taką metodę jako punkt wejścia.
2: Zasadniczo unikałbym tworzenia głównej metody innej niżmain(String[]) .

MC Emperor
źródło
22
„Wydaje mi się, że zamieszanie wynika z faktu, że metoda main (String []) jest używana jako punkt wejścia dla JVM.” mainnie jest punktem wejścia dla JVM. Jest to punkt wejścia, którego javanarzędzie używa do uruchamiania aplikacji. Inne narzędzia (na przykład kontenery serwletów) używają innych punktów wejścia.
TJ Crowder,
27
co jest jeszcze bardziej ironiczne, ponieważ nawet w „kontekście punktu wejścia” główna JUŻ JEST poprawnym identyfikatorem. Tak więc nawet sprawa, którą możesz się temu przeciwstawić, faktycznie dowodzi słuszności OP
Hobbamok,
@TJCrowder Dzięki, zamieściłem to w odpowiedzi.
MC Emperor,
1
@Hobbamok Wydajesz się być zdezorientowany podstawowymi pojęciami Java, co prawdopodobnie wyjaśnia, dlaczego uczysz go w szkole, a nie ćwiczysz - przychodzi na myśl odpowiedź
rath
4
javaNarzędzie nie wymaga main(String[])metody, jeśli głównym klasa rozszerza javafx.application.Application .
VGR
65

Kompiluje się dobrze w Javie 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);
    }
}

... a po wykonaniu generuje dane wyjściowe:

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
źródło
5
Czy można dodać inną static mainmetodę o różnych parametrach?
jpmc26,
6
@ jpmc26 Wypróbuj i powiedz nam, jak poszło. :)
MichaelK
1
Cóż , to dużo dań
MC Emperor
4
@MCEmperor Tak, to mój główny argument za moją odpowiedzią. ;)
MichaelK
3
Zapomniałeś dodać package main;!
Solomon Ucko
45

Rzuciłem w to wszystko, co mogłem, i wydaje się, że działa. Powiedziałbym, że main jest prawidłowym identyfikatorem.

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
źródło
2
Lubię to. Spróbuj 'grep -o main main.java | wc -l '
Gary Bak
3
Ten rodzaj kodu przypomina mi język programowania „ook” ^^ Prawie każde słowo w tym kodzie jest „główne” ...
Florian Bach
public static void main(main...Main)( brak spacji ) nie może działać, prawda?
GeroldBroser przywraca Monikę
3
Czuję się, jakbym to przedstawił.
Ross Presser
1
@GeroldBroser To jest czystsze, ale nie jest absolutnie konieczne: białe spacje między tokenami są w wielu przypadkach opcjonalne, są one wymagane tylko wtedy, gdy połączenie dwóch kolejnych tokenów byłoby również ważne.
MC Emperor
44

Jak mainnie można go użyć jako identyfikatora, gdy jest używany jako identyfikator do deklarowania metody „głównej”?

Dla takiego klasycznego idiomu:

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

main nie jest słowem kluczowym i prawdopodobnie nigdy nie będzie słowem kluczowym w Javie z oczywistych powodów kompatybilności retro.


Jeśli chodzi o pytanie, czy jest mainto dobry identyfikator?

Po pierwsze: poprawne dla kompilatora niekoniecznie musi oznaczać dobre.
Na przykładjava1234 proponowana opcja jest również prawidłowym identyfikatorem, ale tak naprawdę należy jej unikać.

mainma bardzo szczególne i ważne znaczenie: jest stosowany jako metoda wejścia klas i słoików wykonywanych przez javawiersz poleceń.
Użycie mainnazwy metody, która nie spełnia kryteriów używanych w javawierszu poleceń, byłoby po prostu mylące, gdy używałaby jej jako nazwy zmiennej lub nazwy klasy może mieć sens.
Na przykład zdefiniowanie klasy reprezentującej punkt wejścia aplikacji jako Mainklasy aplikacji jest dopuszczalne, dlatego też użycie jej jako nazwy zmiennej, takiej jak:

public class Main {

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

}

Ogólnie rzecz biorąc, w Javie wiele znaków lub „słów” jest uważanych za prawidłowe identyfikatory kompilatora, ale zdecydowanie odradza się ich stosowanie w kodzie klienta (ale generowany kod może to zrobić: na przykład klasy zagnieżdżone) jako nieczytelne i / lub naprawdę wprowadzające w błąd.

Na przykład może to być poprawne dla kompilatora:

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

Ale nie chcemy:

  • nazwać Objectnaszą klasę zgodnie z definicją w java.lang(1).
  • nazwać metodę, main()jeśli nie spełnia kryteriów, które mają być użyte w javalinii poleceń (2).
  • przeładować Object.toString()metodę (3).
  • aby wymienić nasze zmienne z _, $ani żadnych zaskakujących / unmeaningful znaki, które wykraczają przeciwko współdzielonych konwencji nazewnictwa (4).
davidxxx
źródło
7
Dla przypomnienia, mainmoże to być słowo kluczowe, które może być użyte jedynie jako nazwa metody statycznej z odpowiednim podpisem (lub czymkolwiek innym). Zauważ, że wywołania superklasy używają superw taki sposób, że wyglądają jak identyfikator: super(foo);i super.foo, ale superJEST słowem kluczowym (i zanim dodano ogólne, był to jedyny sposób, aby go użyć (co pamiętam)).
jaxad0127,
@ jaxad0127 Ciekawe, ale nie zgadzam się całkowicie. W rzeczywistości tak nie jest, aw przyszłości prawdopodobnie nie byłoby tak z powodów kompatybilności. Jeśli zdefiniowałeś mainjako słowo kluczowe w nowej wersji Java, oznacza to, że żaden kod, który używa main jako nazwy metody (lub dowolnych nazw członków) nie będzie się kompilował. Zastosowanie superw generics nie ma żadnego efektu ubocznego w istniejącym kodzie, ponieważ generics w tym czasie nie istniał.
davidxxx,
2
Chciałem tylko powiedzieć, że MOGŁO to zrobić jako słowo kluczowe. To, że wygląda jak identyfikator, nie oznacza, że ​​musi być.
jaxad0127,
2
Twierdziłbym, że mainwciąż jest to lepszy identyfikator niż java1234. Używanie go do „zwykłej” metody byłoby mylące, ale nie miałbym problemu z nazwaniem zmiennej main, jeśli w rzeczywistości jest to główna rzecz w mojej metodzie. java1234jest po prostu okropny, imiona powinny być opisowe ...
AJPerez,
1
„Jeśli chodzi o pytanie, czy główny jest dobrym identyfikatorem?” To zależy. Prawdopodobnie nie zwróciłbym uwagi na zmienną o nazwie, maingdyby funkcja, na którą patrzyłem, działała z danymi wodnymi. Zwymiotowałbym, gdybym kiedykolwiek zobaczył java1234w kodzie produkcyjnym (i modliłbym się, żeby nie było 1233 innych zmiennych z prefiksem java).
jpmc26,
40

Czy to prawidłowy identyfikator? Tak.

Czy to dobry identyfikator? Nie, jeśli używasz go do czegoś innego niż metoda, która zaczyna się przy uruchomieniu JVM.

Czy wymieniono inny prawidłowy identyfikator? Tak.

Czy instrukcje testowe mówiły, aby wybrać najlepszą odpowiedź?

użytkownik1423956
źródło
7
Uzgodnione - w takim przypadku wielokrotnego wyboru chodzi o wybranie „najlepszej” poprawnej odpowiedzi w przypadku wielu. Nie oznacza to jednak, że jest to dobre pytanie wielokrotnego wyboru i myślę, że należy porozmawiać z nauczycielem na ten temat.
Shadow
19
@Shadow To jest kurs programowania. Niejednoznaczność pytania o coś, co jest określone formalną gramatyką matematyczną, jest nie do przyjęcia. Mówiąc ściśle przeciw temu standardowi (co sugeruje „ ważny ”), obie odpowiedzi są równie poprawne. Mogę sobie wyobrazić o wiele więcej przypadków, w których mainjest to akceptowalny identyfikator, niż ja w którym java1234by to był. Rozważmy na przykład bazę kodu działającą z danymi dotyczącymi zaopatrzenia w wodę (sieć wodociągowa).
jpmc26,
5
Z drugiej strony, java1234 śmierdzi do wysokiego nieba jako identyfikator.
Jozuego
4
„wybierz najlepszą odpowiedź” nie oznacza „dowiedzieć się, kiedy nauczyciel nie wie, o czym mówi, i zgadnij złą odpowiedź, o której myślą”. main to nie tylko prawidłowy identyfikator, to bardzo ważny identyfikator, ponieważ każda aplikacja Java ma główną metodę, a metody są nazywane identyfikatorami.
fluffysheap
2
Uważam tę odpowiedź za bardzo opiniotwórczą i chciałbym móc ją głosować więcej niż raz. Wygląda na to, że próbujesz za wszelką cenę opowiedzieć się po stronie, nie biorąc pod uwagę szerszego obrazu. mainjest idealnie dokładnym identyfikatorem w dowolnym miejscu poza wąską domeną zwykłej aplikacji Java. Może to być nazwa pola w klasie reprezentującej ustawione menu. Lub <main>część dokumentu w kreatorze HTML. java1234z drugiej strony jest tak straszne, jak tylko dostają identyfikatory.
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
źródło
7

Nauczyciel popełnił niewielki błąd, zakładając, że main nie jest prawidłowym identyfikatorem lub po prostu źle sformułował pytanie. Prawdopodobnie chciał powiedzieć „dobry identyfikator”.
Ale ignorowanie argumentów swoich synów, a tym samym zniechęcanie do jego naukowego podejścia do sprawdzania odpowiedniej literatury (specyfikacji Java) i przeprowadzania eksperymentu (pisanie przykładowego programu) jest dokładnym przeciwieństwem tego, co powinien zrobić nauczyciel.

użytkownik82593
źródło
1
Jak zauważono w innych odpowiedziach, mainznacznie częściej jest to „dobry” identyfikator niż java1234byłby. Więc nawet tam nauczyciel się myli. ;)
jpmc26
5

Zarówno maini java123ważne identyfikatory, główny nie jest zarezerwowanym słów kluczowych, dlatego całkowicie dopuszczalne do użycia, o ile test idzie powinien dotarłeś punkt lub pół punktu przynajmniej.

shavar
źródło
5
  1. Powinno być pojedyncze słowo. Oznacza to, że spacje nie są dozwolone.

    Przykład: mangopryka jest ważna, ale cena mango jest nieprawidłowa.

  2. Powinien zaczynać się od litery (alfabetu), podkreślenia lub symbolu $.

    Przykład: cena, cena i cena w USD są ważnymi identyfikatorami.

  3. Nie powinno być słowem kluczowym Java, ponieważ słowo kluczowe ma specjalne znaczenie dla kompilatora.

    Przykład: klasa lub nieważne itp.

  4. Nie powinien zaczynać się od cyfry, ale cyfra może znajdować się na środku lub na końcu.

    Przykład: 5mangoescost jest niepoprawny, a mango5cost i mangocost5 są prawidłowe.

  5. Długość identyfikatora w Javie może wynosić 65 535 znaków i wszystkie są znaczące. W identyfikatorach rozróżniana jest wielkość liter. Oznacza to, że zarówno mango, jak i mango są traktowane inaczej. Może zawierać wszystkie wielkie lub małe litery lub mieszaninę.

IDENTYFIKATOR : są to nazwy klas, nazwy metod, nazwy zmiennych ...

Ponieważ main nie jest słowem zastrzeżonym i zgodnie z powyższym wyjaśnieniem dotyczącym definiowania identyfikatora main jest ważnym identyfikatorem i java1234 również. Pozostałe opcje nie są ważne z powodu powyższego wyjaśnienia.

subhashi
źródło