¿Es posible hacer que las clases internas anónimas en Java estén estáticas?

En Java, las clases anidadas pueden ser static o no. Si son static , no contienen una referencia al puntero de la instancia que los contiene (tampoco se les llama clases internas, se les llama clases anidadas).

Olvidarse de hacer una clase anidada static cuando no necesita esa referencia puede ocasionar problemas con la recolección de basura o el análisis de escape.

¿Es posible hacer una clase interna anónima static también? ¿O el comstackdor lo resuelve automáticamente (que podría, porque no puede haber subclases)?

Por ejemplo, si hago un comparador anónimo, casi nunca necesito la referencia al exterior:

  Collections.sort(list, new Comparator(){ int compare(String a, String b){ return a.toUpperCase().compareTo(b.toUpperCase()); } } 

No, no puedes, y no, el comstackdor no puede resolverlo. Esta es la razón por la cual FindBugs siempre sugiere cambiar las clases internas anónimas a clases anidadas static con nombre si no usan su referencia implícita.

Editar: Tom Hawtin – tackline dice que si la clase anónima se crea en un contexto estático (por ejemplo, en el método main ), la clase anónima es, de hecho, static . Pero el JLS no está de acuerdo :

Una clase anónima nunca es abstract (§8.1.1.1). Una clase anónima es siempre una clase interna (§8.1.3); nunca es static (§8.1.1, §8.5.1). Una clase anónima siempre es implícitamente final (§8.1.1.2).

El Glosario Java de Roedy Green dice que el hecho de que las clases anónimas estén permitidas en un contexto estático depende de la implementación:

Si quieres desconcertar a quienes mantienen tu código, los javac.exe han descubierto que javac.exe permitirá las clases anónimas dentro del código de inicio static y static métodos static , a pesar de que la especificación del lenguaje indica que las clases anónimas nunca son static . Estas clases anónimas, por supuesto, no tienen acceso a los campos de instancia del objeto. No recomiendo hacer esto La función se puede extraer en cualquier momento.

Edición 2: El JLS en realidad cubre contextos estáticos más explícitamente en §15.9.2 :

Deje que C sea ​​la clase que se crea una instancia, y permítame ser la instancia que se está creando. Si C es una clase interna, entonces puedo tener una instancia que encierre inmediatamente. La instancia de I inmediatamente adjunta (§8.1.3) se determina de la siguiente manera.

  • Si C es una clase anónima, entonces:
    • Si la expresión de creación de instancia de clase se produce en un contexto estático (§8.1.3), entonces no tengo ninguna instancia que lo encierre inmediatamente.
    • De lo contrario, la instancia de i que lo rodea inmediatamente es this .

Por lo tanto, una clase anónima en un contexto estático es más o menos equivalente a una clase anidada static , ya que no mantiene una referencia a la clase adjunta, aunque técnicamente no es una clase static .

Creo que hay un poco de confusión en la nomenclatura aquí, que sin duda es demasiado tonto y confuso.

Como sea que los llame, estos patrones (y algunas variaciones con diferente visibilidad) son todos posibles, normales, legales de Java:

 public class MyClass { class MyClassInside { } } public class MyClass { public static class MyClassInside { } } public class MyClass { public void method() { JComponent jc = new JComponent() { ... } } } public class MyClass { public static void myStaticMethod() { JComponent jc = new JComponent() { ... } } } 

Se atienden en la especificación del idioma (si realmente está molesto, consulte la sección 15.9.5.1 para conocer el método estático).

Pero esta cita es simplemente incorrecta :

javac.exe permitirá clases anónimas dentro de código de inicio estático y métodos estáticos, aunque la especificación de idioma indica que las clases anónimas nunca son estáticas.

Creo que el autor citado confunde la palabra clave estática con el contexto estático. (Es cierto que el JLS también es un poco confuso a este respecto).

Honestamente, todos los patrones anteriores están bien (como los llames “nesteds”, “internos”, “anónimos”, etc.). Realmente, nadie va a eliminar de repente esta funcionalidad en la próxima versión de Java. ¡Honestamente!

Mas o menos. Una clase interna anónima creada en un método estático obviamente será efectivamente estática porque no hay una fuente para esto.

Existen algunas diferencias técnicas entre clases internas en contextos estáticos y clases anidadas estáticas. Si estás interesado, lee el JLS 3rd Ed.

Las clases internas no pueden ser estáticas: una clase anidada estática no es una clase interna. El tutorial de Java habla sobre esto aquí .

las clases internas anónimas nunca son estáticas (no pueden declarar métodos estáticos o campos estáticos no finales), pero si están definidas en un contexto estático (método estático o campo estático) se comportan como estáticas en el sentido de que no pueden acceder a miembros no estáticos (es decir, instancia) de la clase adjunta (como todo lo demás desde un contexto estático)

En la nota de hacer una clase interna anónima estática llamándolos dentro de un método estático.

Esto en realidad no elimina la referencia. Puede probar esto tratando de serializar la clase anónima y no hacer que la clase adjunta sea serializable.