Является ли main допустимым идентификатором Java?

Один из моих детей изучает Java в средней школе и на одном из тестов получил следующее:

Which of the following is a valid identifier in Java?

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

Он ответил б и ошибся.

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

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

main - действительный идентификатор?

Мне всегда грустно видеть учителя настолько неуверенным в себе, что он / она боится узнать что-то новое и признать ошибку.

Ryan Lundy 10.10.2018 10:16

я думаю, это так. но вам действительно не следует использовать его в качестве имени переменной / метода (несмотря на очевидный случай), поэтому, если учитель пытается детализировать точку до дома, чтобы подумать - особенно в этом случае - о названиях методов, тогда я могу увидеть его / ее точка.

bharal 10.10.2018 17:21

Действительно ли этот вопрос задает вопрос, правильно ли учитель вашего сына выполняет свою работу? Я вижу два действительных идентификатора Java. Итак, ответ - «b» А ТАКЖЕ «c». Итак, учитель прав. Или я что-то упускаю ?. Как это может быть ТАК вопрос? Судя о каком-то человеке, который даже не является частью сообщества ...

jschnasse 12.10.2018 08:54

Это вопрос об учителях, а не о java.

ACV 15.01.2019 15:47

Еще один из тех случаев, когда «обманули ваш собственный вопрос с подвохом»; Учителя действительно должны хотя бы взглянуть на спецификацию языка, прежде чем пытаться написать такой вопрос на экзамене.

jrh 26.02.2019 22:21
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
289
5
16 416
12
Перейти к ответу Данный вопрос помечен как решенный

Ответы 12

main - допустимый идентификатор Java, и учитель ошибается.

Соответствующая документация находится в Спецификации языка Java, прямо здесь:

Глава 3. «Лексическая структура», раздел 3.8. «Идентификаторы»:

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

Он говорит:

An identifier is an unlimited-length sequence of Java letters and Java digits, the first of which must be a Java letter... An identifier cannot have the same spelling (Unicode character sequence) as a keyword (§3.9), boolean literal (§3.10.3), or the null literal (§3.10.7), or a compile-time error occurs.

Это означает, что вы можете доказать, что это действительный идентификатор:

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

Не могли бы вы процитировать и изложить это более подробно?

zero298 10.09.2018 22:03

нет, потому что это целый раздел. Если учитель думает, что в этом разделе делается какое-то исключение для «основного», именно учитель должен показать, где это сказано.

Mike Nakis 10.09.2018 22:04

main вполне допустим, потому что он, из документов:

  1. Представляет собой «последовательность букв Java и цифр Java, первая из которых является буквой Java».
  2. Не является ключевое слово
  3. Не является логический литерал, т.е. "истина" или "ложь"
  4. Не является нулевой литерал
Ответ принят как подходящий
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:

An identifier is an unlimited-length sequence of Java letters and Java digits, the first of which must be a Java letter.

Identifier:

    IdentifierChars but not a Keyword or BooleanLiteral or NullLiteral

IdentifierChars:

    JavaLetter {JavaLetterOrDigit}

JavaLetter:

    any Unicode character that is a "Java letter"

JavaLetterOrDigit:

    any Unicode character that is a "Java letter-or-digit"

Последовательность символов main соответствует приведенному выше описанию и отсутствует в список ключевых слов в Разделе 3.9.

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

@Clockwork Вопрос был сформулирован так, что только один вариант мог быть правильным. Однако оба варианта бб> и c удовлетворяли условию вопроса, что несовместимо с подразумеваемым выбором. Это оставило ребенка ОП выбирать, какой правильный ответ будет единственным, который учитель посчитал правильным.

rgettman 13.09.2018 22:30

@rgettman Я прочитал "Который из перечисленных..." как разрешающий более одного раза выбор, на который "б и в" будет правильным ответом.

TripeHound 14.09.2018 16:38

@TripeHound "- действительный идентификатор" - единственное число и требует ровно 1 ответа. Сравните это с «действительными идентификаторами»

Gimme the 411 16.09.2018 00:46

Можно было бы сделать и класс main;)

Peter Lawrey 17.09.2018 09:46

Как утверждают другие ответы

main - действительный идентификатор Java, а также java1234.

Я предполагаю, что это сбивает с толку тот факт, что метод main(String[]) часто используется JVM1 в качестве точки входа. Однако это не означает, что сам токен main нельзя использовать в качестве идентификатора 2.

Об этом говорится в спецификации, и следующие декларации также действительны:

  • Поле:

    private int main;
    
  • Локальная переменная:

    String main = "";
    
  • Метод:

    void main() { ... }
    
  • Класс или интерфейс (хотя имя класса или интерфейса, начинающееся с нижнего регистра, не рекомендуется):

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

    package main;
    

1: As noted in the comments, the JVM specification itself does not mandate any particular method as entry point, but the widely used java tool often uses such a method as entry point.
2: I would generally avoid creating a main method other than main(String[]).

«Я полагаю, что сбивает с толку тот факт, что метод main (String []) используется как точка входа для JVM».main не является точкой входа для JVM. Это точка входа, которую инструмент java использует для запуска приложений. Другие инструменты (например, контейнеры сервлетов) используют другие точки входа.
T.J. Crowder 11.09.2018 09:48

что еще более иронично, потому что даже в главном "контексте точки входа" УЖЕ ЕСТЬ действительный идентификатор. Таким образом, даже случай, который вы могли бы возразить, на самом деле доказывает, что OP прав.

Hobbamok 11.09.2018 13:42

@ T.J. Crowder Спасибо, я включил это в ответ.

MC Emperor 11.09.2018 16:21

Объявление 2: И я обычно избегает создания основного метода, отличного от public static void main(String[]). ;)

Gerold Broser 12.09.2018 03:05

@Hobbamok Вы, кажется, не понимаете основных концепций Java, что, вероятно, объясняет, почему вы преподаете его в школе, а не практикуете - ответ, который приходит на ум

rath 12.09.2018 11:58

Инструмент java не требует метода main(String[]), если основной класс расширяет javafx.application.Application.

VGR 12.09.2018 20:27

Как 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).
  • называть наши переменные _, $ или любыми неожиданными / бессмысленными символами, которые противоречат соглашениям об общих именах (4).

Следует отметить, что main может быть ключевым словом, которое можно использовать только как имя для статического метода с соответствующей подписью (или чем-то еще). Обратите внимание, что вызовы суперкласса используют super таким образом, чтобы он выглядел как идентификатор: super(foo); и super.foo, но super ЯВЛЯЕТСЯ ключевым словом (и до того, как были добавлены дженерики, это был единственный способ его использования (насколько я помню)).

jaxad0127 10.09.2018 23:33

@ jaxad0127 Интересный момент, но я не полностью согласен. На самом деле это не так, и в будущем, вероятно, не может быть по причинам совместимости. Если вы определили main как ключевое слово в новой версии java, это означает, что любой код, который использует main как имя метода (или любые имена членов), больше не будет компилироваться. Использование super в дженериках не имеет побочных эффектов в существующем коде, поскольку в то время дженериков не существовало.

davidxxx 10.09.2018 23:50

Я просто имел в виду, что это МОЖНО сделать как ключевое слово. Просто потому, что это похоже на идентификатор, не означает, что так должно быть.

jaxad0127 11.09.2018 00:01

@ jaxad0127 Не углубляясь слишком глубоко в JLS и для двух упомянутых вами случаев, я думаю, можно сказать, что super - это особое выражение: оно представляет собой ссылку на объект Class, который будет использоваться с конструктором объекта и его членами.

Gerold Broser 12.09.2018 02:57

Я бы сказал, что main по-прежнему лучший идентификатор, чем java1234. Использование его для «обычного» метода было бы ошибочным, но у меня не возникло бы проблем с присвоением имени переменной main, если это действительно главное в моем методе. java1234 просто ужасен, названия должны быть описательными ...

AJPerez 12.09.2018 14:56

"Насчет вопроса, является ли main хорошим идентификатором?" Это зависит. Я бы, наверное, и глазом не взглянул на переменную с именем main, если бы функция, на которую я смотрел, что-то делала с данными водопровода. Меня бы вырвало, если бы я Когда-либо увидел java1234 в производственном коде (и молюсь, чтобы не было 1233 других переменных с префиксом java).

jpmc26 13.09.2018 03:59

@ jaxad0127 main можно было бы определить как ключевое слово, он все равно мог бы стать ключевым словом, точно так же, как _ перестал быть законным идентификатором, однако это не так, и это было осознанное решение. Дизайнеры Java решили, что, например, goto и const являются ключевыми словами, чтобы предотвратить их использование в качестве вводящих в заблуждение идентификаторов, но main не требует такой специальной обработки.

Holger 13.09.2018 08:08

@AJPerez Полностью согласен. Но хорошо оба плохие. Вы могли заметить, что я добавил main в качестве имени переменной, но я не цитировал его в вещах, которые нам не нужны (не об опасности). Но я уберу его для единообразия.

davidxxx 13.09.2018 18:10
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);
    }
}

Это отлично компилируется на 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);
    }
}

... и при выполнении производит вывод:

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

Можно ли добавить еще один метод static main с другими параметрами?

jpmc26 13.09.2018 03:50

@ jpmc26 Попробуйте и расскажите, как все прошло. :)

MichaelK 13.09.2018 08:06

Ну это много электросети

MC Emperor 27.09.2018 19:22

@MCEmperor Да, это мой аргумент главный в пользу моего ответа. ;)

MichaelK 27.09.2018 20:04

Вы забыли добавить package main;!

Solomon Ucko 21.02.2019 14:50

Это действительный идентификатор? да.

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

Есть ли в списке другой действительный идентификатор? да.

В инструкциях к тесту говорилось, что нужно выбрать лучший ответ?

Согласовано - подобный множественный выбор касается выбора «наилучшего» правильного ответа, когда их несколько. Однако это не делает этот вопрос хорошим с несколькими вариантами ответов, и я думаю, что поговорить об этом с учителем - это правильно.

Shadow 12.09.2018 05:22

@Shadow Это курс программирования. Двусмысленность в вопросе о том, что определяется формальной математической грамматикой, недопустима. Если говорить строго против этого стандарта (что подразумевается под «действительный»), оба ответа одинаково верны. Я могу представить гораздо больше случаев, в которых main является допустимым идентификатором, чем я могу, когда java1234 был бы. Рассмотрим, например, кодовую базу, работающую с данными о водоснабжении (водопровод).

jpmc26 13.09.2018 03:51

@Holger Я ничего не говорю. Обратите внимание на кавычки вокруг слова лучше. Но очевидно, что этот инструктор так думает.

Shadow 13.09.2018 03:55

@ jpmc26, цитирую самого себя, «это не делает его хорошим вопросом с несколькими вариантами ответов, и я думаю, что поговорить об этом с учителем - это правильно». Пожалуйста, перестаньте притворяться, будто я согласен с тем, что здесь произошло.

Shadow 13.09.2018 03:57

С другой стороны, java1234 воняет до небес как идентификатор.

Joshua 13.09.2018 22:13

«выбрать лучший ответ» не означает «выяснить, когда учитель не знает, о чем они говорят, и угадать плохой ответ, о котором они думают». main - это не только идентификатор действительный, это идентификатор очень важно, потому что каждое приложение Java имеет основной метод, а методы именуются с идентификаторами.

fluffysheap 15.09.2018 12:21

Я считаю этот ответ весьма самоуверенным и хотел бы проголосовать против него более одного раза. Похоже, вы пытаетесь встать на чью-то сторону любой ценой, не учитывая более широкую картину. main - идеальный идентификатор для любого места за пределами узкой области простого Java-приложения. Это может быть имя поля в классе, представляющем заданное меню. Или раздел документа <main> в построителе HTML. java1234, с другой стороны, настолько же ужасен, насколько и идентификаторы.

toniedzwiedz 16.09.2018 10:37

Я бросил на это все, что мог, и, похоже, это сработало. Я бы сказал, что 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;
        }
    }
}

Мне это нравится. Попробуйте 'grep -o main main.java | туалет -l '

Gary Bak 13.09.2018 15:56

Этот код чем-то напоминает мне язык программирования "ook" ^^ Почти каждое слово в этом коде - "main" ...

Florian Bach 14.09.2018 09:50
public static void main(main...Main) (не хватает места) не может работать?
Gerold Broser 14.09.2018 14:50

Я чувствую, что поддержал это.

Ross Presser 15.09.2018 02:56

@GeroldBroser Это чище, но не является строго необходимым: пробелы между токенами во многих случаях необязательны, они требуются только тогда, когда в противном случае было бы допустимо объединение двух последующих токенов.

MC Emperor 23.08.2019 20:19

И main, и java123 являются идентификаторами действительный, main не является зарезервированным ключевым словом, поэтому его вполне можно использовать, что касается теста, вы должны получить как минимум балл или пол-балла.

Этот учитель допустил небольшую ошибку, предположив, что главный не является допустимым идентификатором, или просто неправильно сформулировал вопрос. Возможно, он хотел сказать «хороший идентификатор».
Но игнорирование аргументов ваших сыновей и тем самым препятствование его научному подходу к проверке соответствующей литературы (спецификация Java) и проведению эксперимента (написание примера программы) - это прямо противоположное того, что должен делать учитель.

Как отмечалось в других ответах, main гораздо чаще является «хорошим» идентификатором, чем java1234. Так что даже здесь учитель ошибается. ;)

jpmc26 01.10.2018 09:27
  1. Должно быть одно слово. То есть пробелы не допускаются.

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

  2. Должен начинаться с буквы (алфавита), подчеркивания или символа $.

    Пример: цена, _price и $ price являются допустимыми идентификаторами.

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

    Пример: class или void и т. д.

  4. Не должно начинаться с цифры, но цифра может быть в середине или в конце.

    Пример: 5mangoescost недействителен, а mango5cost и mangocost5 действительны.

  5. Длина идентификатора в Java может составлять 65 535 символов, и все они значимы. Идентификаторы чувствительны к регистру. То есть и к манго, и к манго относятся по-разному. Может содержать все буквы в верхнем или нижнем регистре или их сочетание.

ИДЕНТИФИКАТОР: это имена классов, имена методов, имена переменных ...

Поскольку main не является зарезервированным словом, и в соответствии с приведенным выше объяснением для определения идентификаторов main - действительный идентификатор и java1234 также. Остальные параметры не действительны из-за вышеприведенного объяснения.

Другие вопросы по теме