¿Es main un identificador de Java válido?

288

Uno de mis hijos está tomando Java en la escuela secundaria y tuvo esto en una de sus pruebas:

¿Cuál de los siguientes es un identificador válido en Java?

a. 123java
si. main
C. java1234
re. {abce
mi. )whoot

Él respondió b y se equivocó.

Miré la pregunta y sostuve que main es un identificador válido y que debería haber sido correcto.

Echamos un vistazo a la especificación Java para identificadores y reforzó ese punto. También escribimos un programa de muestra que tenía una variable llamada main, así como un método. Creó una refutación escrita que incluía la referencia de documentación de Java, el programa de prueba y el maestro la ignoró y dice que la respuesta sigue siendo incorrecta.

¿Es mainun identificador válido?

Gary Bak
fuente
12
Siempre me entristece ver a un maestro tan inseguro que tiene miedo de aprender algo nuevo y admitir un error.
Ryan Lundy
creo que es. pero realmente no deberías usarlo como un nombre de variable / método (a pesar del caso obvio), por lo que si el maestro está tratando de profundizar en el punto para pensar, especialmente en este caso, los nombres de los métodos, entonces puedo ver su / su punto
bharal
3
¿Esta pregunta realmente pregunta si el maestro de su hijo está haciendo su trabajo correctamente? Veo dos identificadores Java válidos. Entonces la respuesta es 'b' Y 'c'. Entonces el maestro tiene razón. ¿O me estoy perdiendo algo?. ¿Cómo puede ser esta una pregunta SO? Juzgar por alguna persona que ni siquiera es parte de la comunidad ...
jschnasse
1
Esta es una pregunta sobre los maestros, no sobre Java.
ACV
1
Otro de esos casos "engañados por tu propia pregunta capciosa"; los profesores realmente deberían al menos echar un vistazo a las especificaciones del idioma antes de intentar escribir una pregunta de examen como esta.
jrh

Respuestas:

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

Esto compila, y cuando se ejecuta, emite esta salida:

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

La secuencia de caracteres maines un identificador, no una palabra clave o una palabra reservada.

La sección relevante de la JLS es 3.8 :

Un identificador es una secuencia de letras y dígitos Java de longitud ilimitada , la primera de las cuales debe ser una letra Java .

Identificador:

    IdentifierChars pero no una palabra clave o BooleanLiteral o NullLiteral

IdentifierChars:

    JavaLetter {JavaLetterOrDigit}

JavaLetter:

    cualquier carácter Unicode que sea una "letra Java"

JavaLetterOrDigit:

    cualquier carácter Unicode que sea una "letra o dígito Java"

La secuencia de caracteres se mainajusta a la descripción anterior y no está en la lista de palabras clave en la Sección 3.9 .

(La secuencia de caracteres java1234también es un identificador, por las mismas razones).

rgettman
fuente
25
@Clockwork La pregunta fue formulada de tal manera que solo una opción podría ser correcta. Sin embargo, ambas opciones b y c satisfecho la condición de la cuestión, es incompatible con la opción implícita. Esto dejó al niño del OP elegir entre qué respuesta correcta era la única que el maestro pensaba que era correcta.
rgettman
@rgettman Leí " ¿Cuál de los siguientes ... " que permite elegir más de una vez, a lo que " byc " sería una respuesta válida.
TripeHound
66
@TripeHound "es un identificador válido" es singular y exige exactamente 1 respuesta. Compárelo con "son identificadores válidos"
Dame el 411
2
También podrías haber main
asistido a
97

main es un identificador válido de Java, y el maestro está equivocado.

La documentación relevante está en la Especificación del lenguaje Java, aquí:

Capítulo 3. "Estructura léxica", sección 3.8. "Identificadores":

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

Dice:

Un identificador es una secuencia de letras y dígitos Java de longitud ilimitada, la primera de las cuales debe ser una letra Java ... Un identificador no puede tener la misma ortografía (secuencia de caracteres Unicode) que una palabra clave (§3.9), literal booleano ( §3.10.3), o el literal nulo (§3.10.7), o se produce un error en tiempo de compilación.

Lo que significa que puede probar que es un identificador válido ya sea:

  • buscándolo en la lista de palabras clave de Java (pista: ¡no lo encontrará allí!) o simplemente por
  • usándolo como un identificador y observando que no se produce ningún error en tiempo de compilación.
Mike Nakis
fuente
1
¿Podría citarlo y explicarlo más explícitamente?
zero298
36
no, porque es una sección completa. Si el maestro piensa que esta sección hace algún tipo de excepción para 'main', es el maestro quien debe mostrar dónde lo dice.
Mike Nakis
76

Como dicen las otras respuestas

maines un identificador de Java válido , así como java1234.

Supongo que lo confuso proviene del hecho de que main(String[])la JVM usa el método como punto de entrada 1 a . Sin embargo, eso no significa que el token en mainsí mismo no pueda usarse como identificador 2 .

Las especificaciones lo dicen, y las siguientes declaraciones también son válidas:

  • Un campo:

    private int main;
  • Una variable local:

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

    private void main() { ... }
  • Una clase (aunque se desaconseja un nombre de clase que comience con minúsculas):

    public class main { ... }
  • Un paquete:

    package main;

1: Como se señaló en los comentarios, la especificación JVM en sí misma no exige ningún método en particular como punto de entrada, pero la javaherramienta ampliamente utilizada a menudo usa dicho método como punto de entrada.
2: generalmente evitaría crear un método principal que no sea main(String[]).

MC Emperor
fuente
22
"Supongo que la confusión proviene del hecho de que el método principal (String []) se utiliza como punto de entrada para la JVM". mainno es el punto de entrada para la JVM. Es el punto de entrada que la javaherramienta utiliza para ejecutar aplicaciones. Otras herramientas (contenedores de servlets, por ejemplo) usan otros puntos de entrada.
TJ Crowder
27
lo cual es aún más irónico, porque incluso en el "contexto de punto de entrada" principal YA ES un identificador válido. Por lo tanto, incluso el caso en el que podría oponerse en realidad prueba OP correctamente
Hobbamok el
@TJCrowder Gracias, lo he incluido en la respuesta.
MC Emperor
1
@Hobbamok Pareces confundido acerca de los conceptos básicos de Java, lo que probablemente explica por qué lo enseñas en una escuela y no practicar es la respuesta que viene a la mente
rath
44
La javaherramienta no requiere un main(String[])método si la clase principal extiende javafx.application.Application .
VGR
65

Esto compila bien en 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);
    }
}

... y cuando se ejecuta produce la salida:

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
fuente
55
¿Es posible agregar otro static mainmétodo con diferentes parámetros?
jpmc26
66
@ jpmc26 Pruébalo y cuéntanos cómo te fue. :)
MichaelK
1
Bueno, eso es un montón de platos principales
MC Emperor
44
@MCEmperor Sí, ese es mi argumento principal para mi respuesta. ;)
MichaelK
3
¡Olvidaste agregar package main;!
Solomon Ucko
45

Tiré todo lo que pude, y parece funcionar. Yo diría que main es un 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
fuente
2
Me gusta. Pruebe con 'grep -o main main.java | wc -l '
Gary Bak
3
Ese código me recuerda un poco al lenguaje de programación "ook" ^^ Casi todas las palabras en este código son "principales" ...
Florian Bach
public static void main(main...Main)( falta un espacio ) no puede funcionar, ¿verdad?
GeroldBroser reintegra a Mónica el
3
Siento que lo he marcado.
Ross Presser
1
@GeroldBroser Eso es más limpio, pero no estrictamente necesario: los espacios en blanco entre los tokens son opcionales en muchos casos, solo se requieren cuando la concatenación de dos tokens posteriores también sería válida.
MC Emperor
44

¿Cómo mainno podría usarse como identificador mientras se usa como identificador para declarar el método "principal"?

Para un idioma tan clásico:

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

main no es una palabra clave y probablemente nunca sería una palabra clave en Java por obvias razones de compatibilidad retro.


Sobre la pregunta, ¿es mainun buen identificador?

Primero: válido para un compilador no significa necesariamente bueno.
Por ejemplo, la java1234opción que se propone también es un identificador válido, pero eso realmente debería evitarse.

maintiene un significado muy particular e importante: se utiliza como método de punto de entrada de clases y jarras ejecutadas por la javalínea de comando.
Usar mainun nombre de método que no cumpla con los criterios que usará la javalínea de comando sería engañoso mientras lo usa como nombre de variable o un nombre de clase podría tener sentido.
Por ejemplo, definir la clase que representa el punto de entrada de una aplicación como la Mainclase de la aplicación es aceptable y usarla también como nombre de variable, como por ejemplo:

public class Main {

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

}

De manera general, en Java, varios caracteres o "palabras" se consideran identificadores válidos para el compilador, pero se desaconseja su uso en el código del cliente (pero el código generado puede hacer eso: clases anidadas, por ejemplo) como no legibles y / o realmente engañoso.

Por ejemplo, esto podría ser válido para el 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$);
    }    
}

Pero no queremos:

  • nombrar Objectnuestra clase como se define enjava.lang (1).
  • para nombrar un método main()si no cumple los criterios que utilizará eljava línea de comando (2).
  • sobrecargar el Object.toString() método (3).
  • para nombrar nuestras variables con _, $o cualquier personaje sorprendente / poco significativo que vaya en contra de las convenciones de nomenclatura compartidas (4).
davidxxx
fuente
77
Solo para tener en cuenta, mainpodría ser una palabra clave que solo se puede usar como nombre para un método estático con una firma apropiada (o lo que sea). Tenga en cuenta que las llamadas de superclase se usan superde una manera que lo hace ver como un identificador: super(foo);y super.foo, pero superES una palabra clave (y antes de que se agregaran los genéricos, esta era la única forma de usarlo (que puedo recordar)).
jaxad0127
@ jaxad0127 Punto interesante pero no estoy completamente de acuerdo. En realidad no lo es y en el futuro probablemente no lo sea por razones de compatibilidad. Si definió maincomo una palabra clave en una nueva versión de Java, significa que cualquier código que use main como nombre de método (o cualquier nombre de miembro) ya no se compilará. El uso de supergenéricos no tiene ningún efecto secundario en el código existente ya que los genéricos no existían en este momento.
davidxxx
2
Solo quería decir que PODRÍA haberse hecho como una palabra clave. El hecho de que parezca un identificador no significa que tenga que ser así.
jaxad0127
2
Yo diría que maintodavía es un mejor identificador que java1234. Usarlo para un método "regular" sería engañoso, pero no tendría ningún problema para nombrar una variable main, si en realidad es lo principal en mi método. java1234es horrible, los nombres deben ser descriptivos ...
AJPerez
1
"Sobre la pregunta, ¿es el principal un buen identificador?" Depende. Probablemente no miraría a una variable llamada mainsi la función que estaba mirando hizo algo con los datos principales del agua. Vomitaría si alguna vez viera java1234en el código de producción (y rezara para que no hubiera 1233 otras variables con el prefijo java).
jpmc26
40

¿Es un identificador válido? Si.

¿Es un buen identificador? No, si lo está utilizando para otra cosa que no sea el método que comienza en el lanzamiento de JVM.

¿Hay otro identificador válido en la lista? Si.

¿Las instrucciones del examen decían elegir la mejor respuesta?

usuario1423956
fuente
77
De acuerdo: la opción múltiple como esta se trata de elegir la "mejor" respuesta correcta cuando hay múltiples. Sin embargo, eso no hace que esta sea una buena pregunta de opción múltiple y creo que hablar con el maestro al respecto es lo correcto.
Shadow
19
@Shadow Este es un curso de programación. La ambigüedad en una pregunta sobre algo que se especifica con la gramática matemática formal es intolerable. Hablando estrictamente en contra de ese estándar (que es lo que implica " válido "), ambas respuestas son igualmente correctas. Puedo imaginar muchos más casos en los que maines un identificador tolerable de lo que puedo en lo que java1234sería. Considere, por ejemplo, una base de código que trabaje con datos de suministro de agua (red de agua).
jpmc26
55
Por otro lado, java1234 apesta al cielo como un identificador.
Joshua
44
"elegir la mejor respuesta" no significa "averiguar cuándo el maestro no sabe de qué está hablando y adivinar la mala respuesta en la que está pensando". main no es solo un identificador válido , es un identificador muy importante porque cada aplicación Java tiene un método main, y los métodos se nombran con identificadores.
fluffysheap
2
Encuentro esta respuesta muy obstinada y desearía poder votarla más de una vez. Parece que está tratando de tomar partido a toda costa y no está considerando la imagen más amplia. maines un identificador perfectamente fino en cualquier lugar fuera del dominio estrecho de la aplicación Java simple. Podría ser el nombre de un campo en una clase que representa un menú fijo. O una <main>sección de un documento en un generador de HTML.java1234, por otro lado, es casi tan terrible como los identificadores.
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);
    }
}
ililit
fuente
7

Ese maestro cometió un pequeño error al asumir que main no es un identificador válido o simplemente formular la pregunta incorrectamente. Posiblemente quiso decir "un buen identificador".
Pero ignorar los argumentos de sus hijos y, por lo tanto, desalentar su enfoque científico de verificar la literatura relevante (especificación Java) y realizar un experimento (escribir un programa de muestra) es exactamente lo contrario de lo que se supone que debe hacer un maestro.

usuario82593
fuente
1
Como se señaló en otras respuestas, maines mucho más frecuente que un identificador "bueno" de java1234lo que sería. Entonces, incluso allí, el maestro está equivocado. ;)
jpmc26
5

Ambos mainy java123son identificadores válidos , main no es una palabra clave reservada, por lo que es perfectamente aceptable de usar, en lo que respecta a la prueba, debería haber obtenido un punto o medio punto como mínimo.

Shavar
fuente
5
  1. Debería ser una sola palabra. Es decir, los espacios no están permitidos.

    Ejemplo: el precio del mango es válido pero el precio del mango no es válido.

  2. Debe comenzar con una letra (alfabeto) o guión bajo o símbolo $.

    Ejemplo: price, _price y $ price son identificadores válidos.

  3. No debe ser una palabra clave de Java, ya que la palabra clave tiene un significado especial para el compilador.

    Ejemplo: clase o vacío, etc.

  4. No debe comenzar con un dígito, pero el dígito puede estar en el medio o al final.

    Ejemplo: 5mangoescost no es válido y mango5cost y mangocost5 son válidos.

  5. La longitud de un identificador en Java puede ser de 65.535 caracteres y todos son significativos. Los identificadores distinguen entre mayúsculas y minúsculas. Es decir, tanto el mango como el mango se tratan de manera diferente. Puede contener todas las letras mayúsculas o minúsculas o una mezcla.

IDENTIFICADOR : son nombres de clases, nombres de métodos, nombres de variables ...

Como main no es una palabra reservada y de acuerdo con la explicación anterior para definir un identificador main es un identificador válido y java1234 también. Las opciones restantes no son válidas debido a la explicación anterior.

subhashis
fuente