main是有效的Java标识符吗?


288

我的一个孩子正在读高中的Java,并在他的一项测试中接受了此测试:

以下哪个是Java中的有效标识符?

一个。 123java
b。 main
C。 java1234
d。 {abce
e。 )whoot

他回答b并弄错了。

我看着这个问题,并争辩说这main 一个有效的标识符,应该是正确的。

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

main有效的标识符吗?


12
它总是让我痛心地看到老师如此不安,他/她是害怕学习新的东西,并承认错误。
瑞安·伦迪

我想是的。但您确实不应该将其用作变量/方法名称(尽管有明显的情况),因此,如果老师试图钻研要考虑的重点(尤其是在这种情况下)的方法名称,那么我可以看到他的/她的观点。
巴尔

3
这个问题真的是在问您儿子的老师是否做得正确吗?我看到两个有效的Java标识符。因此答案是“ b” “ c”。所以老师是对的。还是我想念什么?这怎么可能是一个SO问题?判断一个甚至不属于社区的人...
jschnasse

1
这是关于老师的问题,而不是关于Java的问题。
ACV

1
另一个“因您自己的技巧问题而引起”的案例;在尝试编写这样的考试问题之前,老师真的至少应该浏览一下语言规范。
jrh

Answers:


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字母爪哇位,其中第一个必须是一个爪哇字母

识别码:

    IdentifierChars,但不是关键字,BooleanLiteral或NullLiteral

标识符字符:

    JavaLetter {JavaLetterOrDigit}

JavaLetter:

    任何“ Java字母”的Unicode字符

JavaLetterOrDigit:

    任何“ Java字母或数字”的Unicode字符

字符序列main符合上述说明,不在3.9节关键字列表中

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


25
@Clockwork这个问题的措词是,只有一种选择是正确的。但是,选择bc都满足问题的条件,与隐含选择不一致。这使OP的孩子可以选择哪个正确答案是唯一的一个老师认为正确的答案。
rgettman

@rgettman我读了“ 以下哪个... ”,因为它允许多次选择,对“ b和c ”将是一个有效的响应。
TripeHound18年

6
@TripeHound“是有效的标识符”是单数形式,需要精确的1个答案。把它比作“是有效的标识符”
给我的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
您能否更明确地引用和说明?
Zero298 '18

36
不,因为它是整个部分。如果老师认为本节对“主要”有所例外,则必须由老师来说明。
Mike Nakis

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
“我想这个混淆来自于将main(String [])方法用作JVM的入口点这一事实。” main不是JVM的入口点。这是该java工具用于运行应用程序的切入点。其他工具(例如servlet容器)使用其他入口点。
TJ Crowder

27
甚至具有讽刺意味的是,因为即使在“入口点上下文”中,主主体也已经是有效的标识符。因此,即使您可以反对的情况也确实证明了OP的权利
Hobbamok

@TJCrowder谢谢,我已将其包含在答案中。
MC Emperor

1
@Hobbamok 您似乎对Java的基本概念感到困惑,这很可能解释了为什么您在学校教它而不是实践是想到的答案
rath

4
如果主类扩展了javafx.application.Application,则该java工具不需要main(String[])方法。
VGR

65

可以在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

5
是否可以添加其他static main具有不同参数的方法?
jpmc26,1

6
@ jpmc26试试看,并告诉我们它如何进行。:)
MichaelK

1
,这是很多电源
MC Emperor

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 | 厕所-l”
加里·巴克

3
该代码有点让我想起了编程语言“ ook” ^^这段代码中几乎每个单词都是“ main” ...
Florian Bach

public static void main(main...Main)缺少空格)不能工作,可以吗?
GeroldBroser在18:50恢复莫妮卡

3
我感觉像是主线。
Ross Presser

1
@GeroldBroser这是更清洁的方法,但并非绝对必要:在许多情况下,标记之间的空格是可选的,仅当两个后续标记的串联也有效时才需要使用空格。
MC Emperor

44

main用作声明“ main”方法的标识符时,如何不能用作标识符?

对于这样的经典习语:

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

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


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

第一:对编译器有效并不意味着一定是好的。
例如java1234,建议的选项也是有效的标识符,但实际上应避免使用。

main具有非常特别和重要的意义:它用作java命令行执行的类和jar的入口点方法。
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)任何奇怪/ unmeaningful字符。

7
仅需注意,main可以是仅可用作带有适当签名(或其他任何签名)的静态方法的名称的关键字。请注意,超级类调用的使用super方式使其看起来像标识符:super(foo);super.foo,但它super是关键字(并且在添加泛型之前,这是使用它的唯一方法(我记得)。
jaxad0127 '18

@ jaxad0127有趣的一点,但我不同意。实际上并非如此,将来出于兼容性原因可能也不会。如果您main在Java的新版本中将其定义为关键字,则意味着使用main作为方法名(或任何成员名)的任何代码将不再编译。superin泛型的使用在现有代码中没有任何副作用,因为此时不存在泛型。
davidxxx

2
我只是说它可以作为关键字完成。仅仅因为它看起来像一个标识符,并不意味着它一定是必需的。
jaxad0127 '18

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应用程序都有一个main方法,并且方法都以标识符命名。
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

那个老师在假设main不是有效的标识符或者只是简单地将问题表达为错误时犯了一个小错误。他可能打算说“一个很好的标识符”。
但是,无视儿子的论点,从而挫败他检查相关文献(Java规范)和进行实验(编写示例程序)的科学方法,与教师应该做的恰恰相反


1
正如在其他答案中指出的那样,main通常是“好”标识符java1234。所以即使在那里,老师也是错的。;)
jpmc26

5

这两个mainjava123有效的标识符,主要不是保留关键字所以这是完全可以接受的使用,尽可能的去测试,你应该已经得到了至少一个点或半个点。


5
  1. 应该是一个字。那是不允许的空格。

    示例:mangoprice有效,但mango价格无效。

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

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

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

    例如:class或void等。

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

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

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

IDENTIFIER:它们是类名,方法名,变量名...

由于main不是保留字,根据上面的定义标识符的说明,main是有效的标识符 java1234也是如此。由于上述说明,其余选项无效。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.