Main é um identificador Java válido?

288

Um dos meus filhos está cursando Java no ensino médio e fez isso em um de seus testes:

Qual das alternativas a seguir é um identificador válido em Java?

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

Ele respondeu be entendeu errado.

Eu olhei para a pergunta e argumentei que main é um identificador válido e que deveria estar certo.

Examinamos a especificação Java para identificadores e isso reforçou esse ponto. Também escrevemos um programa de amostra que tinha uma variável chamada main, além de um método. Ele criou uma refutação por escrito que incluiu a referência da documentação Java, o programa de teste e o professor a ignorou e diz que a resposta ainda está incorreta.

É mainum identificador válido?

Gary Bak
fonte
12
Sempre me entristece ver um professor tão inseguro que ele / ela tem medo de aprender algo novo e admitir um erro.
Ryan Lundy
eu acho que é. mas você realmente não deve usá-lo como um nome de variável / método (apesar do caso óbvio), por isso, se o professor estiver tentando detalhar o ponto inicial para ter em consideração - especialmente neste caso - nomes de métodos, então eu posso ver seu / o ponto dela.
bharal
3
Esta pergunta realmente pergunta se o professor do seu filho está fazendo o trabalho corretamente? Eu vejo dois identificadores Java válidos. Portanto, a resposta é 'b' AND 'c'. Então o professor está correto. Ou eu estou esquecendo de alguma coisa?. Como isso pode ser uma pergunta SO? A julgar sobre alguma pessoa que não é nem mesmo parte da comunidade ...
jschnasse
1
Esta é uma pergunta sobre professores, não sobre java.
ACV
1
Outro daqueles casos "enganados por sua própria pergunta enganosa"; os professores realmente deveriam, pelo menos, dar uma olhada nas especificações do idioma antes de tentar escrever uma pergunta do exame como esta.
Jrh

Respostas:

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

Isso compila e, quando executado, emite esta saída:

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

A sequência de caracteres mainé um identificador, não uma palavra-chave ou palavra reservada.

A seção relevante do JLS é 3.8 :

Um identificador é uma sequência de letras e dígitos Java ilimitada , a primeira das quais deve ser uma letra Java .

Identificador:

    IdentifierChars, mas não uma palavra-chave ou BooleanLiteral ou NullLiteral

IdentifierChars:

    JavaLetter {JavaLetterOrDigit}

JavaLetter:

    qualquer caractere Unicode que seja uma "letra Java"

JavaLetterOrDigit:

    qualquer caractere Unicode que seja "letra ou dígito Java"

A sequência de caracteres mainse encaixa na descrição acima e não está na lista de palavras - chave na Seção 3.9 .

(A sequência de caracteres java1234também é um identificador, pelos mesmos motivos.)

rgettman
fonte
25
@ Clockwork A pergunta foi formulada de tal forma que apenas uma opção pudesse estar correta. No entanto, ambas as opções b e c satisfeita a condição da pergunta, inconsistente com a escolha implícita. Isso deixou o filho do OP escolher entre qual resposta correta era a única que o professor achou correta.
Rgettman # 13/18
@rgettman Eu li " Qual das seguintes opções ... " como permitindo mais de uma vez a escolha, para qual " bec " seria uma resposta válida.
TripeHound 14/09
6
@TripeHound "é um identificador válido" é singular e exige exatamente 1 resposta. Compare com "são identificadores válidos"
Gimme # 411
2
Você poderia ter feito a classe mainbem;)
Peter Lawrey
97

main é um identificador java válido e o professor está errado.

A documentação relevante está na Especificação da linguagem Java, aqui:

Capítulo 3. "Estrutura Lexical", seção 3.8. "Identificadores":

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

Diz:

Um identificador é uma sequência de tamanho e letras Java ilimitada, a primeira das quais deve ser uma letra Java ... Um identificador não pode ter a mesma ortografia (sequência de caracteres Unicode) que uma palavra-chave (§3.9), literal booleano ( §3.10.3), ou o literal nulo (§3.10.7), ou ocorre um erro em tempo de compilação.

O que significa que você pode provar que é um identificador válido:

  • procurando na lista de palavras-chave java (dica: você não a encontrará lá!) ou simplesmente
  • usando-o como um identificador e observando que nenhum erro em tempo de compilação ocorre.
Mike Nakis
fonte
1
Você poderia citar e explicitar de maneira mais explícita?
precisa saber é o seguinte
36
não, porque é uma seção inteira. Se o professor acha que esta seção faz algum tipo de exceção para 'main', é o professor que deve mostrar onde diz isso.
Mike Nakis 10/09
76

Como as outras respostas declaram

mainé um identificador Java válido , bem como java1234.

Eu acho que a confusão vem do fato de que o main(String[])método é frequentemente usado como ponto de entrada pela JVM 1 . No entanto, isso não significa que o mainpróprio token não possa ser usado como identificador 2 .

As especificações dizem isso e as seguintes declarações também são válidas:

  • Um campo:

    private int main;
  • Uma variável local:

    String main = "";
  • Um método:

    private void main() { ... }
  • Uma classe (embora um nome de classe que comece com minúsculas seja desencorajado):

    public class main { ... }
  • Um pacote:

    package main;

1: Conforme observado nos comentários, a própria especificação da JVM não exige nenhum método específico como ponto de entrada, mas a javaferramenta amplamente usada geralmente usa esse método como ponto de entrada.
2: Eu geralmente evitaria criar um método principal diferente de main(String[]).

MC Emperor
fonte
22
"Eu acho que a confusão vem do fato de que o método main (String []) é usado como ponto de entrada para a JVM." mainnão é o ponto de entrada para a JVM. É o ponto de entrada que a javaferramenta usa para executar aplicativos. Outras ferramentas (contêineres de servlet, por exemplo) usam outros pontos de entrada.
TJ Crowder
27
o que é ainda mais irônico, porque mesmo no "contexto do ponto de entrada" principal JÁ É um identificador válido. Assim, mesmo o caso, você poderia prender contra ele realmente prova OP direito
Hobbamok
@TJCrowder Obrigado, incluí isso na resposta.
MC Emperor
1
@Hobbamok Você parece confuso sobre conceitos de Java básicos, o que provavelmente explica por que você ensiná-la em uma escola e não pratica é a resposta que vem à mente
Rath
4
A javaferramenta não requer um main(String[])método se a classe principal estender javafx.application.Application .
VGR 12/09
65

Isso compila bem no 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);
    }
}

... e quando executado produz a saída:

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
fonte
5
É possível adicionar outro static mainmétodo com parâmetros diferentes?
Jpmc26 13/09/2018
6
@ jpmc26 Experimente e conte-nos como foi. :)
MichaelK
1
Bem, isso é muita corrente
MC Emperor
4
@MCEmperor Sim, esse é o meu principal argumento para a minha resposta. ;)
MichaelK
3
Você esqueceu de adicionar package main;!
Solomon Ucko
45

Joguei tudo o que pude e parece que funciona. Eu diria que main é um identificador válido.

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
fonte
2
Eu gosto disso. Experimente um 'grep -o main main.java | wc -l '
Gary Bak
3
Esse código meio faz-me lembrar a linguagem de programação "ook" ^^ Quase cada palavra neste código é "main" ...
Florian Bach
public static void main(main...Main)( faltando um espaço ) não pode funcionar, pode?
GeroldBroser restabelece Monica 14/09
3
Eu sinto que eu o destaquei.
Ross Presser
1
@GeroldBroser Isso é mais limpo, mas não estritamente necessário: os espaços em branco entre os tokens são, em muitos casos, opcionais, são necessários apenas quando a concatenação de dois tokens subsequentes também seria válida.
MC Emperor
44

Como mainnão pôde ser usado como identificador enquanto é usado como identificador para declarar o método "principal"?

Para um idioma tão clássico:

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

main não é uma palavra-chave e provavelmente nunca seria uma palavra-chave em Java por razões óbvias de compatibilidade retroativa.


Sobre a pergunta, é mainum bom identificador?

Primeiro: válido para um compilador não significa necessariamente bom.
Por exemplo, a java1234opção proposta também é um identificador válido, mas que realmente deve ser evitado.

maintem um significado muito particular e importante: é usado como o método de ponto de entrada de classes e jarros executados pela javalinha de comando.
Usar mainum nome de método que não preencha os critérios a serem usados ​​pela javalinha de comando seria enganoso, mas usá-lo como nome de variável ou nome de classe pode fazer sentido.
Por exemplo, definir a classe que representa o ponto de entrada de um aplicativo como a Mainclasse do aplicativo é aceitável e, portanto, usá-lo também como nome de variável, como:

public class Main {

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

}

De maneira geral, em Java, vários caracteres ou "palavras" são considerados identificadores válidos para o compilador, mas são fortemente desencorajados a serem usados ​​no código do cliente (mas o código gerado pode fazer isso: classes aninhadas por exemplo) como não legíveis e / ou realmente enganoso.

Por exemplo, isso pode ser válido para o compilador:

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

Mas nós não queremos:

  • para nomear Objectnossa classe, conforme definido em java.lang(1).
  • nomear um método main()se não preencher os critérios a serem usados ​​pela javalinha de comando (2).
  • sobrecarregar o Object.toString()método (3).
  • para citar nossos variáveis com _, $ou quaisquer caracteres surpreendentes / unmeaningful que vão contra as convenções de nomenclatura comum (4).
davidxxx
fonte
7
Apenas para observar, mainpoderia ser uma palavra-chave que só pode ser usada como um nome para um método estático com uma assinatura apropriada (ou qualquer outra coisa). Observe que as chamadas de superclasse usam superde uma maneira que faz com que pareça um identificador: super(foo);e super.foo, mas superé uma palavra-chave (e antes da inclusão de genéricos, essa era a única maneira de usá-la (que eu me lembro)).
precisa saber é o seguinte
@ jaxad0127 Ponto interessante, mas não concordo completamente. Na verdade, não é e, no futuro, provavelmente não seria por motivos de compatibilidade. Se você definiu maincomo uma palavra-chave em uma nova versão do java, significa que qualquer código que use main como nome do método (ou qualquer nome de membro) não será mais compilado. O uso de superem genéricos não tem nenhum efeito colateral no código existente, pois os genéricos não existiam no momento.
Davidxxx # 10/18
2
Eu apenas quis dizer que poderia ter sido feito como uma palavra-chave. Só porque parece um identificador, não significa que tem que ser.
precisa saber é o seguinte
2
Eu diria que mainainda é um identificador melhor do que java1234. Usá-lo para um método "regular" seria enganoso, mas não teria problemas em nomear uma variável main, se ela for realmente a principal coisa no meu método. java1234é simplesmente horrível, nomes deve ser descritivo ...
AJPerez
1
"Sobre a questão, o principal é um bom identificador?" Depende. Provavelmente, eu não daria uma mainolhada em uma variável chamada se a função que eu estava vendo fizesse algo com os dados principais da água. Eu ia vomitar se eu vi java1234no código de produção (e rezar não havia 1.233 outras variáveis com prefixo java).
Jpmc26 13/09/19
40

É um identificador válido? Sim.

É um bom identificador? Não se você o estiver usando para algo diferente do método iniciado no lançamento da JVM.

Há outro identificador válido listado? Sim.

As instruções do teste disseram para escolher a melhor resposta?

user1423956
fonte
7
Concordado - a escolha múltipla como esta diz respeito à escolha da 'melhor' resposta correta quando houver várias. No entanto, isso não faz desta uma boa pergunta de múltipla escolha e acho que conversar com o professor sobre isso é a coisa certa a se fazer.
Shadow
19
@ Shadow Este é um curso de programação. A ambiguidade em uma pergunta sobre algo especificado com gramática matemática formal é intolerável. Falando estritamente contra esse padrão (que é o que está implícito em " válido "), ambas as respostas estão igualmente corretas. Posso imaginar muito mais casos em que mainé um identificador tolerável do que posso java1234. Considere, por exemplo, uma base de código que trabalha com dados de fornecimento de água (rede de distribuição de água).
Jpmc26 13/09/19
5
Por outro lado, java1234 fede ao alto céu como um identificador.
Joshua Joshua
4
"escolher a melhor resposta" não significa "descobrir quando o professor não sabe do que está falando e adivinhar a resposta ruim em que está pensando". main não é apenas um identificador válido , é um identificador muito importante porque todo aplicativo Java possui um método principal, e os métodos são nomeados com identificadores.
precisa saber é o seguinte
2
Acho esta resposta altamente opinativa e gostaria de poder votá-la mais de uma vez. Parece que você está tentando se posicionar a todo custo e sem considerar a imagem mais ampla. mainé um identificador perfeitamente preciso em qualquer lugar fora do domínio restrito do aplicativo Java comum. Pode ser o nome de um campo em uma classe que representa um menu fixo. Ou uma <main>seção de um documento em um construtor HTML. java1234, por outro lado, é tão terrível quanto os identificadores.
toniedzwiedz
29

mainé perfeitamente válido porque, nos documentos :

  1. É uma "sequência de letras e dígitos Java, o primeiro dos quais é uma letra Java"
  2. Não é uma palavra - chave
  3. Não é um literal booleano, ou seja, "verdadeiro" ou "falso"
  4. Não é literal nulo
zero298
fonte
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
fonte
7

Esse professor cometeu um pequeno erro ao supor que main não é um identificador válido ou simplesmente colocar a pergunta errada. Ele possivelmente quis dizer "um bom identificador".
Mas ignorar os argumentos de seus filhos e, assim, desencorajar sua abordagem científica de verificar literatura relevante (especificação Java) e realizar um experimento (escrever um programa de amostra) é exatamente o oposto do que um professor deve fazer.

user82593
fonte
1
Como observado em outras respostas, mainé muito mais frequentemente um identificador "bom" do que java1234seria. Então, mesmo lá, o professor está errado. ;)
jpmc26 1/01/18
5

Ambos maine java123são identificadores válidos , main não é uma palavra-chave reservada, por isso é perfeitamente aceitável de usar; no que diz respeito ao teste, você deveria ter conseguido um ponto ou meio ponto pelo menos.

shavar
fonte
5
  1. Deve ser uma palavra. Ou seja, espaços não são permitidos.

    Exemplo: o mangoprice é válido, mas o preço da manga não é válido.

  2. Deve começar com uma letra (alfabeto) ou sublinhado ou $.

    Exemplo: price, _price e $ price são identificadores válidos.

  3. Não deve ser uma palavra-chave do Java, pois a palavra-chave carrega um significado especial para o compilador.

    Exemplo: classe ou nulo etc.

  4. Não deve começar com um dígito, mas o dígito pode estar no meio ou no final.

    Exemplo: 5mangoescost não é válido e mango5cost e mangocost5 são válidos.

  5. O comprimento de um identificador em Java pode ter 65.535 caracteres e todos são significativos. Identificadores diferenciam maiúsculas de minúsculas. Isso é manga e manga são tratadas de maneira diferente. Pode conter todas as letras maiúsculas ou minúsculas ou uma mistura.

IDENTIFICADOR : são nomes de classe, nomes de métodos, nomes de variáveis ​​...

Como main não é uma palavra reservada e, de acordo com a explicação acima para definir um identificador, main é um identificador válido e java1234 também. As opções restantes não são válidas devido à explicação acima.

subhashis
fonte