289

One of my kids is taking Java in high school and had this on one of his tests:

Which of the following is a valid identifier in Java?

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

He answered b and got it wrong.

I looked at the question and argued that main is a valid identifier and that it should have been right.

We took a look at the Java spec for identifiers and it reinforced that point. We also wrote a sample program that had a variable called main, as well as a method. He created a written rebuttal that included the Java documentation reference, the test program and the teacher ignored it and says the answer is still incorrect.

Is main a valid identifier?

Community
  • 1
  • 1
Gary Bak
  • 4,564
  • 4
  • 19
  • 32
  • 15
    It always makes me sad to see a teacher so insecure that he/she is afraid to learn something new and admit a mistake. – Ryan Lundy Oct 10 '18 at 08:16
  • i guess it is. but you really shouldn't be using it as a variable/method name (obvious case notwithstanding), so if the teacher is trying to drill the point home to be thoughtful about - especially in this case - method names then i can see his/her point. – bharal Oct 10 '18 at 15:21
  • 3
    Does this question really ask, if your son's teacher is doing his job correctly? I see two valid Java identifiers. So the answer is 'b' **AND** 'c'. So the teacher is correct. Or am I missing something?. How can this be a SO question? Judging about some person who isn't even part of the community... – jschnasse Oct 12 '18 at 06:54
  • 1
    This is a question about teachers, not about java. – ACV Jan 15 '19 at 14:47
  • 1
    Another one of those "tricked by your own trick question" cases; teachers really should at least glance at the language spec before attempting to write an exam question like this. – jrh Feb 26 '19 at 21:21

12 Answers12

254
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.)

Community
  • 1
  • 1
rgettman
  • 167,281
  • 27
  • 248
  • 326
  • 25
    @Clockwork The question was worded such that only one choice could be correct. However, both choices **b** and **c** satisfied the question's condition, inconsistent with the implied choice. This left the OP's child to choose between which correct answer was the one the only one that teacher thought was correct. – rgettman Sep 13 '18 at 20:30
  • @rgettman I read "_Which of the following..._" as allowing more than once choice, to which "_b and c_" would be a valid response. – TripeHound Sep 14 '18 at 14:38
  • 7
    @TripeHound "is a valid identifier" is singular and demands exactly 1 answer. Compare it to "are valid identifiers" – Gimme the 411 Sep 15 '18 at 22:46
  • 2
    You could have made the class `main` as well ;) – Peter Lawrey Sep 17 '18 at 07:46
97

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.
Mike Nakis
  • 46,450
  • 8
  • 79
  • 117
  • 1
    Could you quote and spell it out more explicitly? – zero298 Sep 10 '18 at 20:03
  • 36
    no, because it is an entire section. If the teacher thinks that this section makes some sort of exception for 'main', it is the teacher who must show where it says so. – Mike Nakis Sep 10 '18 at 20:04
78

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:

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

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

MC Emperor
  • 17,266
  • 13
  • 70
  • 106
  • 23
    *"I guess the confusing comes from the fact that the main(String[]) method is used as entry point for the JVM."* `main` isn't the entry point for the JVM. It's the entry point that the `java` tool uses to run applications. Other tools (servlet containers, for instance) use other entry points. – T.J. Crowder Sep 11 '18 at 07:48
  • 27
    which is even more ironic, because even in the "entry-point-context" main ALREADY IS a valid identifier. So even the case you could hold against it actually proves OP right – Hobbamok Sep 11 '18 at 11:42
  • @T.J.Crowder Thanks, I've included that in the answer. – MC Emperor Sep 11 '18 at 14:21
  • Ad 2: And **I** would generally avoid creating a main method other than `public static void main(String[])`. ;) – Gerold Broser Sep 12 '18 at 01:05
  • 1
    @Hobbamok _You seem confused about basic Java concepts, which probably explains why you teach it in a school and not practicing_ is the reply that comes to mind – rath Sep 12 '18 at 09:58
  • 4
    The `java` tool does not require a `main(String[])` method if the main class extends [javafx.application.Application](https://docs.oracle.com/javase/10/docs/api/javafx/application/Application.html). – VGR Sep 12 '18 at 18:27
65

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
MichaelK
  • 2,494
  • 1
  • 11
  • 14
45

I threw everything I could at it, and it appears to work. I'd say main is a valid identifier.

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;
        }
    }
}
18107
  • 688
  • 5
  • 9
  • 2
    I like it. Try a 'grep -o main main.java | wc -l' – Gary Bak Sep 13 '18 at 13:56
  • 3
    That code kinda reminds me of the programming language "ook" ^^ Almost every word in this code is "main" ... – Florian Bach Sep 14 '18 at 07:50
  • `public static void main(main...Main)` ([missing a space](https://docs.oracle.com/javase/8/docs/technotes/guides/language/varargs.html)) can't work, can it? – Gerold Broser Sep 14 '18 at 12:50
  • 3
    I feel like I mainlined it. – Ross Presser Sep 15 '18 at 00:56
  • 1
    @GeroldBroser That is cleaner, but not strictly necessary: whitespaces between tokens are in many cases optional, they're only required when the concatenation of two subsequent tokens would otherwise also be valid. – MC Emperor Aug 23 '19 at 18:19
44

How main could not be used as an identifier while it is used as identifier to declare the "main" method ?

For such a classic idiom :

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

main is not a keyword and it would probably never be a keyword in Java for obvious retro compatibility reasons.


About the question, is main a good identifier ?

First : valid for a compiler doesn't mean necessarily good.
For example the java1234 option that is proposed is also a valid identifier but that should really be avoided.

main has a very particularly and important meaning : it is used as the entry point method of classes and jars executed by the java command line.
Using main for a method name that doesn't fill the criteria to be used by the java command line would be just misleading while using it as variable name or a class name could make sense.
For example defining the class representing the entry point of an application as the Main class of the application is acceptable and so using it as variable name too such as :

public class Main {

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

}

In a general way, in Java, multiple characters or "words" are considered valid identifiers for the compiler but are strongly discouraged to be used in the client code (but generated code may do that : nested classes for example) as not readable and/or really misleading.

For example this could be valid for the compiler :

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

But we don't want :

  • to name Object our class as this is defined in java.lang(1).
  • to name a method main() if doesn't fill the criteria to be used by the java command line (2).
  • to overload the Object.toString() method (3).
  • to name our variables with _, $ or any surprising/unmeaningful characters that go against the shared naming conventions (4).
davidxxx
  • 104,693
  • 13
  • 159
  • 179
  • 7
    Just to note, `main` could be a keyword that is only usable as a name for a static method with an appropriate signature (or whatever). Note that super class calls use `super` in a way that makes it look like an identifier: `super(foo);` and `super.foo`, but `super` IS a keyword (and before generics were added, this was the only way to use it (that I can remember)). – jaxad0127 Sep 10 '18 at 21:33
  • @jaxad0127 Interesting point but I don't agree completely. Actually it IS not and in the future it could probably not be for still compatibility reasons. If you defined `main` as a keyword in a new version of java, it means that any code that uses main as method name (or any member names) will not compile any longer. The usage of `super` in generics doesn't have any side effect in existing code as generics didn't exist at this time. – davidxxx Sep 10 '18 at 21:50
  • 2
    I just meant that it COULD have been done as a keyword. Just because it looks like an identifier, doesn't mean it has to be. – jaxad0127 Sep 10 '18 at 22:01
  • @jaxad0127 Without going too deep into the JLS and for the two cases you mention I think it can be said that `super` is a special expression: It represents a reference to a `Class` object to be used with the object's constructor and its members. – Gerold Broser Sep 12 '18 at 00:57
  • 2
    I would argue that `main` is still a better identifier than `java1234`. Using it for a "regular" method would be misleading, but I'd have no problem naming a variable `main`, if it's actually the main something in my method. `java1234` is just awful, names should be descriptive... – AJPerez Sep 12 '18 at 12:56
  • 1
    "About the question, is main a good identifier?" It depends. I probably wouldn't bat an eye at a variable named `main` if the function I was looking at did something with water main data. I'd throw up if I *ever* saw `java1234` in production code (and pray there were not 1233 other variables with the prefix `java`). – jpmc26 Sep 13 '18 at 01:59
  • @jaxad0127 `main` could have been defined to be a keyword, it could still become a keyword, just like `_` stopped to be a legal identifier, however, it is not and this was a deliberate decision. The Java designers decided that, e.g. `goto` and `const` are keywords, to prevent their use as misleading identifiers, but `main` does not require such special treatment. – Holger Sep 13 '18 at 06:08
  • @AJPerez I completely agree. But well both are bad. You could notice that I added `main` as variable name but I didn't quote it in things that we don't want (not the hazard). But I will remove it to be consistent. – davidxxx Sep 13 '18 at 16:10
40

Is it a valid identifier? Yes.

Is it a good identifier? Not if you're using it for anything other than the method that starts at JVM launch.

Is another valid identifier listed? Yes.

Did the test instructions say to choose the best answer?

user1423956
  • 449
  • 3
  • 3
  • 7
    Agreed - multiple choice like this are about choosing the 'best' correct answer when there are multiple. However, that doesn't make this a good multiple choice question and I think talking to the teacher about it is the right thing to do. – Shadow Sep 12 '18 at 03:22
  • 19
    @Shadow This is a programming course. Ambiguity on a question about something that's specified with formal mathematical grammar is intolerable. Speaking strictly against that standard (which is what's implied by "**valid**"), both answers are equally correct. I can imagine far more cases in which `main` is a tolerable identifier than I can in which `java1234` would be. Consider, for example, a code base working with water supply data (water mains). – jpmc26 Sep 13 '18 at 01:51
  • 1
    @Holger I'm not saying anything. Please note the quotes around the word better. But clearly this instructor thinks so. – Shadow Sep 13 '18 at 01:55
  • 1
    @jpmc26 to quote myself, "this doesn't make it a good multiple choice question and I think talking to the teacher about it is the right thing to do". Please stop pretending that I agree with what has happened here. – Shadow Sep 13 '18 at 01:57
  • 5
    On the other hand, java1234 stinketh to high heaven as an identifier. – Joshua Sep 13 '18 at 20:13
  • 4
    "choose the best answer" doesn't mean "figure out when the teacher doesn't know what they're talking about and guess the bad answer they are thinking of." main is not only a *valid* identifier, it's a *very important* identifier because every Java application has a main method, and methods are named with identifiers. – fluffysheap Sep 15 '18 at 10:21
  • 2
    I find this answer highly opinionated and I wish I could down-vote it more than once. It seems you're trying to take a side at all cost and not considering the broader picture. `main` is a perfectly fine identifier anywhere outside the narrow domain of plain Java application. It could be the name of a field in a class representing a set menu. Or a `
    ` section of a document in an HTML builder. `java1234`, on the other hand, is about as terrible as identifiers get.
    – toniedzwiedz Sep 16 '18 at 08:37
29

main is perfectly valid because it, from the docs:

  1. Is a "sequence of Java letters and Java digits, the first of which is a Java letter"
  2. Is not a keyword
  3. Is not a boolean literal i.e. "true" or "false"
  4. Is not null literal
zero298
  • 20,481
  • 7
  • 52
  • 83
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);
    }
}
ililit
  • 1,259
  • 1
  • 12
  • 18
7

That teacher made a minor mistake in either assuming main is not a valid identifier or simply phrasing the question wrong. He possibly meant to say "a good identifier".
But ignoring your sons arguments and thereby discouraging his scientific approach of checking relevant literature (Java specification) and performing an experiment (writing a sample program) is the exact opposite of what a teacher is supposed to do.

user82593
  • 171
  • 8
  • 1
    As noted on other answers, `main` is much more often a "good" identifier than `java1234` would be. So even there, the teacher is wrong. ;) – jpmc26 Oct 01 '18 at 07:27
5

Both main and java123 are valid identifiers, main isn’t a reserved keyword so it’s perfectly acceptable to use, as far as the test goes you should’ve gotten a point or half a point at least.

Chirag Jain
  • 1,329
  • 9
  • 25
shavar
  • 81
  • 6
5
  1. Should be single word. That is spaces are not allowed.

    Example: mangoprice is valid but mango price is not valid.

  2. Should start with a letter (alphabet) or underscore or $ symbol.

    Example: price, _price and $price are valid identifiers.

  3. Should not be a keyword of Java as keyword carries special meaning to the compiler.

    Example: class or void etc.

  4. Should not start with a digit but digit can be in the middle or at the end.

    Example: 5mangoescost is not valid and mango5cost and mangocost5 are valid.

  5. Length of an identifier in Java can be of 65,535 characters and all are significant. Identifiers are case-sensitive. That is both mango and Mango are treated differently. Can contain all uppercase letters or lowercase letters or a mixture.

IDENTIFIER: they are class names, method names, variable names ...

As main is not a reserved word and according to the explanation above for defining an identifier main is a valid identifier and java1234 also.Remaining options are not valid because of the above explanation.

subhashis
  • 4,173
  • 7
  • 35
  • 49