Is main a valid Java identifier?

Solution 1:

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

This compiles, and when executed, emits this output:

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

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

The 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"

The character sequence main fits the above description and is not in the keyword list in Section 3.9.

(The character sequence java1234 is also an identifier, for the same reasons.)

Solution 2:

main is a valid java identifier, and the teacher is wrong.

The relevant documentation is in the Java Language Specification, right here:

Chapter 3. "Lexical Structure", section 3.8. "Identifiers":

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

It says:

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.

Which means that you can prove that it is a valid identifier either by:

  • looking for it in the list of java keywords (hint: you won't find it there!) or simply by
  • using it as an identifier and observing that no compile-time error occurs.

Solution 3:

As the other answers state

main is a valid Java identifier, as well as java1234.

I guess the confusing comes from the fact that the main(String[]) method is often used as entry point by the JVM1. However, that doesn't mean that the token main itself cannot be used as identifier2.

The specs say so, and the following declarations are also valid:

  • A field:

    private int main;
    
  • A local variable:

    String main = "";
    
  • A method:

    void main() { ... }
    
  • A class or interface (although a class or interface name starting with lowercase is discouraged):

    class main { ... }
    
  • A package:

    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[]).


Addendum: I don't feel like this is the place to rant, but here is my correct humble opinion: the identifier main is just as valid as java1234, so both must be treated equally valid or wrong. Doing otherwise is intolerable.

Solution 4:

This compiles fine on 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);
    }
}

...and when executed produces the output:

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