2012-02-03 33 views
11

He aprendido que la única clase pública en un archivo Java también debe tener el método principal. Sin embargo, a continuación, ¿puede ver el método principal dentro de una clase interna? ¿Cuál es la regla con respecto a la definición del método principal en un archivo fuente?Método principal en una clase interna estática.

public class TestBed { 
    public TestBed() { 
     System.out.println("Test bed c'tor"); 
    } 

    @SuppressWarnings("unused") 
    private static class Tester { 
     public static void main(String[] args) { 
      TestBed tb = new TestBed(); 
      tb.f(); 
     } 
    } 

    void f() { 
     System.out.println("TestBed::f()"); 
    } 
} 
+0

que debería funcionar si se hace público que la clase interna. – Thilo

+0

Funciona como es. En mi caso, sin embargo, tuve que escapar del carácter '$' para iniciar desde el shell: '$ java TestBed \ $ Tester' – Vlad

+0

@Thilo - la clase NESTED necesita ** no ** para ser pública. Ser público solo era cierto para las (muy) primeras versiones de Java. Hoy en día, Java es lo suficientemente inteligente como para encontrar el método en clases privadas (probado con Java 5, 6 y 7 en Windows XP) –

Respuesta

5

Si desea iniciar una clase con Java (Java lanzador: java test.MyClass) entonces esta clase debe tener una método principal con la firma conocida.

Puede tener un método principal con la misma firma en cualquier lugar que desee. Pero no espere que el lanzador lo encuentre.

P.S. El nombre del idioma es Java, no JAVA.

No es un dato menor:

Usted puede hacer esto:

package test; 

public class Test { 

    /** 
    * @param args the command line arguments 
    */ 
    static public class A { 

     public static void main(String[] args) { 
      System.err.println("hi"); 
     } 
    } 
} 

java test.Test $ A

pero esto no es normal ...

+0

Me pregunto si funcionará en este caso, ya que la clase que contiene el método principal es privada, estática y no se usa en ninguna parte. –

+1

@KurtDuBois - funciona, pero debe usar el nombre de clase correcto 'TestBed $ Tester' para iniciarlo. –

+1

Tenga en cuenta que cuando se ejecuta en un shell \ * nix, es probable que tenga que escapar del '$': 'java test.Test \ $ A'. –

2

Cada aplicación Java debe tener un método principal. Es el punto de partida para la ejecución del código en la aplicación. Su firma del método es:

public static void main(String[] args) 

Una clase interna estática es una clase que se define dentro de la definición de una clase diferente y marcado como estático.

Por ejemplo, si la clase externa se llama TestBed, entonces una clase interna de TestBed, que se llama Tester, se compilaría en TestBed $ Tester.class. La separación de los archivos .class significa que puede mantener el código complementario y anidado estrechamente acoplado a la clase primaria primaria.

Están en el mismo archivo fuente, y la clase interna está realmente dentro de la clase externa. Todo eso y no tiene que pagar ningún tipo de despliegue o costo de tiempo de ejecución.

Al usar clases internas estáticas, puede agregar funcionalidad de soporte adicional a sus sistemas para capacidades tales como las pruebas, sin incurrir en penalizaciones en la implementación de producción normal.

Para ejecutar el método main() de la clase TestBed.Tester,

% java TestBed$Tester 
+0

siendo pedante: por definición (JLS 8.1.3) una _ clase interna_ es una clase anidada que ** no ** declara como 'estática'! –

4

Cualquier clase que puede tener un método estático puede tener un public static void main(String[] args).

Esto incluye:

clases de nivel superior (ya sea pública o no), por ejemplo,

public class Foo { 
    public static void main(String[] args) { 
     System.out.println("Hello"); 
    } 
} 

y clases internas estáticas (ya sean públicas o no) (como en el ejemplo).

No incluye:

  • clases anónimas
  • clases no estáticos internos

por lo que ambos de ellos son ilegales:

public class Foo { 
    private Object bar = new Object() { 
     public static void main(String[] args) { 
      System.out.println("Hello"); 
     } 
    }; 
} 


public class Foo { 
    private class Bar { 
     public static void main(String[] args) { 
      System.out.println("Hello"); 
     } 
    }; 
} 
+0

pedantic: _inner classes_ no ** tiene ** un método estático - JLS 8.1.3: '[...] Las clases internas no pueden declarar inicializadores estáticos (§8.7) o interfaces de miembros [...]'. No hay clases _inner static_, por definición (JLS 8.1.3 nuevamente) y _inner class_ es una clase anidada no estática. –

+0

@CarlosHeuberger Tienes toda la razón. Estaba descuidado en mi terminología, usando la palabra "interno" intercalablemente con "anidado". –

+0

Digamos que una clase pública tiene un método principal y la clase tiene una clase interna estática con el método principal. ¿Cómo encontraría JVM y qué parte de la clase que tiene el método principal? ¿Cómo resuelve las dos clases? – user3705478

-1

Esto es interesante como el el código se compilará y ejecutará en Eclipse, pero solo compilará desde el uso de la línea de comando. Cuando se ejecuta desde eclipse, encontrará el método principal estático desde dentro de la clase interna y lo ejecutará.

Pero al ejecutar java TestBed desde la línea de comandos obtendrá el error - Exception in thread "main" java.lang.NoSuchMethodError: main que es un error válido ya que no ha definido su método principal en la clase principal.

¿Por qué querrías definir tu método principal en una clase interna? Su método principal debe definirse en clase pública, esta no es una regla sino una práctica común.

En código de abajo He movido el principal método en la clase externa que funciona tanto en línea Eclipse & comando:

public class TestBed { 
    public TestBed() { 
     System.out.println("Test bed c'tor"); 
    } 

    @SuppressWarnings("unused") 
    private static class Tester { 

    } 

    public static void main(String[] args) { 
     TestBed tb = new TestBed(); 
     tb.f(); 
    } 

    void f() { 
     System.out.println("TestBed::f()"); 
    } 
} 
+0

Incorrecto: línea de comando - 'java TestBed $ Tester' - funciona bien (Windows XP, Java 6 y 7) y no es necesario que la clase tenga el método principal para ser público. –

+0

Por supuesto, java TestBed $ Tester funciona bien, Java Tester no lo hará. "No hay necesidad de que la clase tenga el método principal para ser público". Me doy cuenta de que no es necesario, solo estaba sugiriendo qué es una práctica común, al menos en lo que he visto. Nunca he visto la necesidad de declarar una clase principal "final" o "abstracta". –

+0

sure 'java Tester' no funcionará, tampoco en Eclipse. Debe usar el nombre de clase correcto y completamente calificado. Y no solo estabas '' simplemente sugiriendo lo que es una práctica común '' - escribiste que 'solo compilará desde el uso de la línea de comando' (pero no se ejecutará) - eso está mal - ¡se ejecuta desde la línea de comando! ¿Qué hay de "final" o "abstracto"? Usted es el primero en usar estos términos aquí (por cierto, el resumen no se compilará con estática, y el principal debe ser estático). –

Cuestiones relacionadas