main 是有效的 Java 标识符吗?

Is main a valid Java identifier?

我的一个孩子正在 Java 上高中,并且在他的一次考试中有这个:

Which of the following is a valid identifier in Java?

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

他回答了 b 并且答错了。

我查看了这个问题并认为 main 一个有效的标识符,它应该是正确的。

我们查看了 Java spec 标识符,它强化了这一点。我们还编写了一个示例程序,其中包含一个名为 main 的变量以及一个方法。他创建了一个书面反驳,其中包括 Java 文档参考、测试程序和老师忽略它并说答案仍然不正确。

main 是有效的标识符吗?

main是有效的java标识符,老师错了。

相关文档在 Java 语言规范中,就在这里:

第 3 章 "Lexical Structure",第 3.8 节。 "Identifiers":

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 关键字列表中查找它(提示:您不会在那里找到它!)或直接通过
  • 将其用作标识符并观察没有发生编译时错误。

main 完全有效,因为 from the docs:

  1. 是一个"sequence of Java letters and Java digits, the first of which is a Java letter"
  2. 不是 keyword
  3. 不是 boolean literal 即 "true" 或 "false"
  4. 不是null literal
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是标识符,不是关键字或保留字。

relevant section of the JLS is 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符合上述描述,不在keyword list in Section 3.9.

(字符序列java1234也是一个标识符,原因相同。)

正如其他答案所述

main 是有效的 Java 标识符 ,以及 java1234.

我想造成混淆的原因是 main(String[]) 方法经常被 JVM1 用作入口点。然而,这并不意味着令牌 main 本身不能用作标识符 2.

规范是这样说的,以下声明也是有效的:

  • 一个字段:

    private int main;
    
  • 局部变量:

    String main = "";
    
  • 一个方法:

    void main() { ... }
    
  • A class 或接口(尽管不鼓励以小写字母开头的 class 或接口名称):

    class main { ... }
    
  • 一个包裹:

    package main;
    

1:如评论中所述,JVM 规范本身并未强制要求任何特定方法作为入口点,但广泛使用的 java 工具通常使用此类方法作为入口点.
2:我通常会避免创建除 main(String[]).

以外的主要方法

附录:我不觉得这是吐槽的地方,但这是我的正确的 谦虚 意见:标识符 mainjava1234 一样有效,因此两者必须同等有效或错误。否则是不能容忍的。

main作为标识符声明"main"方法时,如何不能作为标识符使用?

对于这样的 classic 成语:

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

main 不是关键字,出于明显的复古兼容性原因,它可能永远不会成为 Java 中的关键字。


关于这个问题,main 是一个好的标识符吗?

首先:对编译器有效并不意味着一定好。
例如,提议的 java1234 选项也是一个有效的标识符,但实际上应该避免这种情况。

main有一个特别重要的意义:作为java命令行执行的classes和jar的入口方法
使用 main 作为不符合 java 命令行使用标准的方法名称只会产生误导,而将其用作变量名称或 class 名称可能有意义.
例如,将表示应用程序入口点的 class 定义为应用程序的 Main class 是可以接受的,因此也可以将其用作变量名称,例如:

public class Main {

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

}

一般来说,在 Java 中,多个字符或 "words" 被认为是编译器的有效标识符,但强烈建议不要在客户端代码中使用(但生成的代码可能会这样做) : 例如嵌套 classes) 不可读 and/or 确实具有误导性。

例如,这可能对编译器有效:

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 我们的 class,因为这是在 java.lang(1) 中定义的。
  • 命名方法 main() 如果不满足 java 命令行 (2) 使用的条件。
  • 重载 Object.toString() 方法 (3)。
  • 使用 _$ 或任何违反共享命名约定的 surprising/unmeaningful 字符命名我们的变量 (4)。
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

它是一个有效的标识符吗?是的

它是一个好的标识符吗?如果您将它用于 JVM 启动时启动的方法之外的任何其他用途,则不会。

是否列出了另一个有效标识符?是的

测试说明有没有说要选择最佳答案?

我竭尽全力,它似乎奏效了。我会说 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;
        }
    }
}

mainjava123都是有效的标识符,main不是保留关键字所以完全可以使用,就测试而言你至少应该得到一分或半分。

那位老师犯了一个小错误,要么假设 main 不是有效的标识符,要么只是问题的措辞有误。他可能是想说 "a good identifier"。
但是无视你儿子的论点,从而阻止他检查相关文献(Java 规范)和进行实验(编写示例程序)的科学方法是 完全相反的 老师应该做的。

  1. 应该是一个单词。那就是不允许有空格。

    示例:芒果价格有效但芒果价格无效。

  2. 应以字母(字母)或下划线或 $ 符号开头。

    示例:price、_price 和 $price 是有效标识符。

  3. 不应该是 Java 的关键字,因为关键字对编译器具有特殊含义。

    例如:class或void等

  4. 不应以数字开头,但数字可以在中间或末尾。

    示例:5mangoescost 无效,而 mango5cost 和 mangocost5 有效。

  5. Java 中标识符的长度可以是 65,535 个字符,并且都是有效的。 标识符区分大小写。那就是芒果和芒果的区别对待。 可以包含所有大写字母或小写字母或混合。

IDENTIFIER:它们是class个名字,方法名,变量名...

因为 main 不是保留字,根据上面定义标识符的解释 main 是一个有效的标识符java1234[=由于上述解释,45=] also.Remaining 选项无效。