Чи є основним дійсний ідентифікатор Java?


288

Один з моїх дітей брав Java в середній школі і мав це на одному з своїх тестів:

Що з наведеного нижче є дійсним ідентифікатором на Java?

а. 123java
б. main
c. java1234
г. {abce
е. )whoot

Він відповів b і зрозумів неправильно.

Я переглянув питання і стверджував, що main це дійсний ідентифікатор і що воно повинно було бути правильним.

Ми розглянули специфікацію Java для ідентифікаторів, і це посилило цю точку. Ми також написали зразкову програму, яка мала змінну, що називається main, а також метод. Він створив письмове спростування, яке містило посилання на документацію Java, тестову програму, а вчитель проігнорував це і каже, що відповідь досі невірна.

Чи mainдійсний ідентифікатор?


12
Мені завжди сумно бачити вчителя настільки невпевнено, що він / вона боїться дізнатися щось нове і визнати помилку.
Райан Лунді

я здогадуюсь, це так. але ви дійсно не повинні використовувати його як назву змінної / методу (незважаючи на очевидний випадок), тому, якщо вчитель намагається пробурити точку додому, щоб бути продуманим - особливо в цьому випадку - назви методів, то я можу побачити його / її точка.
бхарал

3
Чи справді це запитання, якщо вчитель вашого сина виконує свою роботу правильно? Я бачу два дійсних ідентифікатори Java. Отже, відповідь - "b" ТА "c". Тож учитель правильний. Або я щось пропускаю ?. Як це може бути питанням SO? Судячи про людину, яка навіть не є частиною спільноти ...
jschnasse

1
Це питання про вчителів, а не про Java.
ACV

1
Ще один із тих випадків, які "обдурені вашим власним підступним питанням"; викладачі дійсно повинні хоча б поглянути на мовні характеристики перед тим, як спробувати написати подібне екзаменаційне запитання.
jrh

Відповіді:


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

Цей компілюється і після його виконання видає цей вихід:

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

Послідовність символів main- це ідентифікатор, а не ключове слово або зарезервоване слово.

Відповідний розділ JLS є 3,8 :

Ідентифікатор є послідовністю необмеженої довжини Java букв і Java цифр , перша з яких повинна бути буква Java .

Ідентифікатор:

    IdentifierChars, але не ключове слово або BooleanLiteral або NullLiteral

Характеристики ідентифікатора:

    JavaLetter {JavaLetterOrDigit}

JavaLetter:

    будь-який символ Unicode, який є "літерою Java"

JavaLetterOrDigit:

    будь-який символ Unicode, який є "буквою або цифрою Java"

Послідовність символів mainвідповідає вищеописаному опису і не міститься у списку ключових слів у Розділі 3.9 .

(Послідовність символів java1234також є ідентифікатором з тих же причин.)


25
@Clockwork Питання було сформульовано таким чином, що лише один вибір міг бути правильним. Однак обидва варіанти b і c задовольняли умову питання, що не відповідало передбачуваному вибору. Це дозволило дитині ОП вибрати, яка правильна відповідь була єдиною, яку вчитель вважав правильною.
rgettman

@rgettman Я читав " Яке з наступного ... " як таке, що не раз допускає вибір, на яке " b і c " було б дійсною відповіддю.
TripeHound

6
@TripeHound "правильний ідентифікатор" є єдиним і вимагає рівно 1 відповіді. Порівняйте його з "дійсними ідентифікаторами"
дайте Gimme the 411

2
Ви могли також зробити клас main;)
Пітер Лорі

97

main є дійсним ідентифікатором Java, а вчитель помиляється.

Відповідна документація знаходиться в специфікації мови Java, тут:

Глава 3. "Лексична структура", розділ 3.8. "Ідентифікатори":

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

Він говорить:

Ідентифікатор - це необмежена послідовність букв Java та цифр Java, першою з яких повинна бути буква Java ... Ідентифікатор не може мати те саме написання (послідовність символів Unicode), як ключове слово (§3.9), булевий буквальний ( §3.10.3), або нульове буквальне (§3.10.7), або помилка часу компіляції.

Що означає, що ви можете довести, що це дійсний ідентифікатор, або:

  • шукайте його у списку ключових слів Java (підказка: ви його там не знайдете!) або просто від
  • використовуючи його як ідентифікатор і спостерігаючи, що не виникає помилка часу компіляції.

1
Не могли б ви процитувати і прописати це більш чітко?
нуль298

36
ні, тому що це цілий розділ. Якщо вчитель вважає, що цей розділ робить якийсь виняток для "основного", саме вчитель повинен показати, де це сказано.
Майк Накіс

76

Як свідчать інші відповіді

mainє дійсним ідентифікатором Java , а також java1234.

Я думаю, що заплутаність походить від того, що main(String[])метод JVM 1 часто використовується як точка входу . Однак це не означає, що сам маркер mainне може використовуватися як ідентифікатор 2 .

Технічні характеристики говорять про це, і такі декларації також дійсні:

  • Поле:

    private int main;
  • Локальна змінна:

    String main = "";
  • Спосіб:

    private void main() { ... }
  • Клас (хоча ім’я класу, що починається з малих літер, не рекомендується):

    public class main { ... }
  • Пакет:

    package main;

1: Як зазначено в коментарях, сама специфікація JVM не передбачає конкретного методу в якості точки входу, але широко використовуваний javaінструмент часто використовує такий метод як точка входу.
2: Я б взагалі уникав створення іншого, ніж іншого main(String[]).


22
"Я думаю, що заплутаність пов'язана з тим, що основний (String []) метод використовується в якості точки входу в JVM." mainне є точкою входу для СВМ. Це точка входу, яку javaінструмент використовує для запуску програм. Інші інструменти (наприклад, контейнери сервлетів) використовують інші точки входу.
TJ Crowder

27
що ще іронічніше, адже навіть у контексті "вхідної точки-точки" НАДЕЖДА Є дійсним ідентифікатором. Тож навіть справа, яку ви могли б проти цього, насправді підтверджує право ОП
Хоббамок,

@TJCrowder Дякую, я включив це у відповідь.
MC Імператор

1
@Hobbamok Ви здаєтеся розгубленими щодо основних понять Java, що, ймовірно, пояснює, чому ви вчите це в школі, а не практикуєте, - це відповідь, що спадає на думку
рат

4
javaІнструмент не вимагає main(String[])методу , якщо основний клас розширює javafx.application.Application .
VGR

65

Це добре поєднує Java Java ...

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

... і при виконанні видає результат:

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

5
Чи можна додати інший static mainметод з різними параметрами?
jpmc26

6
@ jpmc26 Спробуйте це і розкажіть нам, як це пройшло. :)
MichaelK

1
Ну ось багато мереж
MC імператор

4
@MCEmperor Так, це мій головний аргумент для моєї відповіді. ;)
MichaelK

3
Ви забули додати package main;!
Соломон Учко

45

Я кинув усе, що міг, і, схоже, спрацював. Я б сказав, що main - це дійсний ідентифікатор.

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

2
Мені це подобається. Спробуйте 'grep -o main main.java | wc -l '
Gary Bak

3
Цей код ніби нагадує мені мову програмування "ок" ^^ Майже кожне слово в цьому коді є "головним" ...
Флоріан Бах,

public static void main(main...Main)( пропущений пробіл ) не може працювати, чи не так?
ГерольдБрозер повертає Моніку

3
Я відчуваю, що я це підкреслив.
Росс Пресер

1
@GeroldBroser Це чистіше, але не дуже суворо: пробіли між маркерами в багатьох випадках необов’язкові, вони потрібні лише тоді, коли конкатенація двох наступних жетонів також була б дійсною.
MC Імператор

44

Як main не можна використовувати як ідентифікатор, тоді як він використовується як ідентифікатор для оголошення "основного" методу?

Для такої класичної ідіоми:

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

main це не ключове слово, і це, ймовірно, ніколи не буде ключовим словом на Java з очевидних причин ретро сумісності.


Щодо питання, чи є main хороший ідентифікатор?

По-перше: дійсний для компілятора не означає обов'язково добре.
Наприкладjava1234 варіант також є дійсним ідентифікатором, але цього слід уникати.

mainмає дуже особливе і важливе значення: він використовується як метод точки введення класів і jar, виконаних javaкомандним рядком.
Використання mainдля імені методу, який не заповнює критерії, що використовуються в javaкомандному рядку, було б просто оманливим при використанні його як імені змінної або імені класу може мати сенс.
Наприклад, визначення класу, що представляє точку входу програми як Mainклас програми, є прийнятним, і таким чином, використовуючи його як назву змінної, наприклад:

public class Main {

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

}

Загалом у Java кілька символів або "слів" вважаються дійсними ідентифікаторами для компілятора, але сильно не рекомендується використовувати їх у клієнтському коді (але згенерований код може це робити: наприклад, вкладені класи) як нечитабельні та / або насправді вводить в оману.

Наприклад, це може бути дійсним для компілятора:

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

Але ми не хочемо:

  • назвати Objectнаш клас так, як це визначено вjava.lang (1).
  • назвати метод, main()якщо він не заповнює критерії, якими повинен користуватисяjava командним рядком (2).
  • перевантажувати Object.toString() метод (3).
  • назвати наші змінні з _, $або будь-якими несподіваними / unmeaningful символів , які йдуть проти спільних угод про іменах (4).

7
Зауважимо, це mainможе бути ключове слово, яке можна використовувати лише як ім'я для статичного методу з відповідною підписом (або будь-яким іншим). Зауважте, що виклики суперкласу використовують superтак, щоб він виглядав як ідентифікатор: super(foo);і super.foo, але superце ключове слово IS (і до того, як були додані дженерики, це був єдиний спосіб його використання (що я пам'ятаю)).
jaxad0127

@ jaxad0127 Цікавий момент, але я не згоден повністю. Насправді це НЕ, і в майбутньому це, мабуть, не може бути з причин сумісності. Якщо ви визначили mainключове слово в новій версії Java, це означає, що будь-який код, який використовує main як ім'я методу (або будь-які імена учасників), більше не збиратиметься. Використання superв дженериках не має жодного побічного ефекту в існуючому коді, оскільки генерики на даний момент не існували.
davidxxx

2
Я просто мав на увазі, що це МОЖЕ бути зроблено як ключове слово. Тільки тому, що він схожий на ідентифікатор, не означає, що він повинен бути.
jaxad0127

2
Я б заперечив, що mainце все-таки кращий ідентифікатор, ніж java1234. Використовувати його для "звичайного" методу було б вводити в оману, але я б не мав проблем з назвою змінної main, якщо це насправді головне в моєму методі. java1234просто жахливо, назви повинні бути описовими ...
AJPerez

1
"Що стосується питання, чи є головним хороший ідентифікатор?" Це залежить. Я, мабуть, не кинув очей на змінну з назвою, mainякби функція, на яку я дивився, робила щось із основними даними води. Я б кинув, якби коли-небудь бачив java1234у виробничому коді (і молюсь, щоб не було 1233 інших змінних з префіксом java).
jpmc26

40

Це дійсний ідентифікатор? Так.

Це хороший ідентифікатор? Не якщо ви використовуєте його для чогось іншого, крім методу, який починається при запуску JVM.

Чи вказаний ще один дійсний ідентифікатор? Так.

Чи сказали інструкції з тесту, щоб вибрати найкращу відповідь?


7
Погоджено - подібний вибір багато в чому полягає у виборі "найкращої" правильної відповіді, коли їх багато. Однак, це не робить це гарним питанням з множинним вибором, і я думаю, що говорити з викладачем про це правильно.
Тінь

19
@Shadow Це курс програмування. Неоднозначність у питанні про щось, що визначено формальною математичною граматикою, нестерпне. Якщо говорити суворо проти цього стандарту (що означає " дійсне "), обидві відповіді однаково правильні. Я можу уявити набагато більше випадків, коли mainідентифікатор є терпимим, ніж я міг java1234би бути. Розглянемо, наприклад, кодову базу, яка працює з даними про водопостачання (водопровід).
jpmc26

5
З іншого боку, java1234 смердить на високе небо як ідентифікатор.
Джошуа

4
"вибрати найкращу відповідь" не означає "з'ясувати, коли вчитель не знає, про що вони говорять, і вгадає погану відповідь, про який думає". main - це не лише дійсний ідентифікатор, це дуже важливий ідентифікатор, оскільки кожен додаток Java має основний метод, а методи іменовані ідентифікаторами.
Fluffysheap

2
Я вважаю, що ця відповідь є дуже впевненою, і я хочу, щоб я міг її проголосувати не один раз. Здається, ви намагаєтесь зайнятись стороною за будь-яку ціну і не розглядаєте більш широку картину. main- це ідеальний ідентифікатор у будь-якій точці за межами вузького домену простого додатка Java. Це може бути назва поля в класі, що представляє меню набору. Або <main>розділ документа в HTML-програмі. java1234з іншого боку, настільки ж жахливо, як ідентифікатори.
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);
    }
}

7

Цей викладач допустив незначну помилку, вважаючи, що головний не є дійсним ідентифікатором, або просто неправильно формулює питання. Він, можливо, мав намір сказати "хороший ідентифікатор".
Але ігнорування аргументів ваших синів і тим самим відлякує його науковий підхід до перевірки відповідної літератури (специфікація Java) та проведення експерименту (написання зразкової програми) - це точно протилежне тому, що повинен робити вчитель.


1
Як зазначається в інших відповідях, mainнабагато частіше "хороший" ідентифікатор, ніж java1234був би. Так що навіть там вчитель помиляється. ;)
jpmc26

5

Обидва mainі java123є дійсними ідентифікаторами, main не є зарезервованим ключовим словом, тому його цілком прийнятно використовувати, що стосується тесту, ви мали б отримати бал або хоча б пів бала.


5
  1. Повинно бути одним словом. Тобто пробіли не допускаються.

    Приклад: мангоціна дійсна, але ціна манго не вірна.

  2. Починати слід з літери (алфавіту) або підкреслення або символу $.

    Приклад: ціна, _ціна та ціна $ є дійсними ідентифікаторами.

  3. Не повинно бути ключовим словом Java, оскільки ключове слово має особливе значення для компілятора.

    Приклад: клас чи недійсність тощо

  4. Не слід починати з цифри, але цифра може бути в середині або в кінці.

    Приклад: 5mangoescost недійсний, а mango5cost і mangocost5 є дійсними.

  5. Довжина ідентифікатора на Java може становити 65535 символів, і всі вони значущі. Ідентифікатори залежать від регістру. Тобто і до манго, і до манго трактуються по-різному. Може містити всі великі літери або малі літери або суміш.

ІДЕНТИФІЄР : це назви класів, назви методів, назви змінних ...

Оскільки main не є зарезервованим словом, і відповідно до пояснення вище, для визначення ідентифікатора main є допустимим ідентифікатором, а також java1234. Залишилися параметри недійсні через вищезазначене пояснення.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.