java java-7 diamond-operator

¿Por qué no se puede usar Java 7 diamond operator con clases anónimas?



java-7 diamond-operator (4)

Desde Java 10 , puede hacer fácilmente con var , el compilador se encargará de la inferencia de tipo.

var list1 = new ArrayList(); var list2 = new ArrayList<String>(); var list3 = new ArrayList<String>() { }; var list4 = new ArrayList<>() { }; var list5 = new ArrayList<Integer>() { };

Considere este código Java que intenta crear una instancia de algunas List :

List<String> list1 = new ArrayList<String>(); List<String> list2 = new ArrayList<>(); List<String> list3 = new ArrayList<String>() { }; List<String> list4 = new ArrayList<>() { }; List<String> list5 = new ArrayList<Integer>() { };

list1 y list2 son simples; list2 usa el nuevo operador de diamante en Java 7 para reducir la repetición innecesaria de los parámetros de tipo.

list3 es una variación de list1 usa una clase anónima, posiblemente para anular algunos métodos de ArrayList .

list4 intenta usar el operador diamond, similar a list2 , pero este es un error de compilación, con el mensaje ''<>'' no se puede usar con clases anónimas .

list5 produce un error que demuestra que el compilador sabe qué tipo es realmente necesario. El mensaje de error es Tipo no coincidente: no se puede convertir de nuevo ArrayList <Integer> () {} a List <String>

Entonces, con la declaración de list4 , ¿por qué no se puede usar el operador de diamante con clases anónimas? Aquí hay una pregunta similar con una respuesta aceptada que contiene la siguiente explicación de JSR-334 :

No se admite el uso de rombos con clases internas anónimas, ya que hacerlo en general requeriría que las extensiones del atributo de firma del archivo de clase representen tipos no denotables, un cambio de JVM de facto.

Necesito ayuda para entender ese razonamiento. ¿Por qué un tipo explícito versus el tipo idéntico y aparentemente fácilmente inferible requiere alguna diferencia en el archivo de clase resultante? ¿Qué caso de uso difícil se cubriría con "hacerlo en general"?

¿Cuál es la razón subyacente para esto?


Esto fue discutido en la lista de correo "Project Coin" . En sustancia (el énfasis es mío):

Internamente, un compilador Java opera sobre un conjunto de tipos más rico que los que se pueden anotar explícitamente en un programa Java. Los tipos internos del compilador que no se pueden escribir en un programa Java se llaman tipos no denotables. Los tipos no denotables pueden ocurrir como resultado de la inferencia utilizada por el diamante. Por lo tanto, no se admite el uso de rombos con clases internas anónimas, ya que hacerlo en general requeriría extensiones del atributo de firma del archivo de clase para representar tipos no denotables, un cambio de JVM de facto . Es posible que las futuras versiones de plataforma permitan el uso de diamantes al crear una clase interna anónima, siempre que el tipo inferido sea denotable.

Tenga en cuenta que tampoco es compatible con Java 8, pero se incluirá como una nueva característica en Java 9 (Elemento 3 de "Moneda del proyecto de fresado" ).


Puede usar el abrelatas de diamante en Java9

MyHandler<Integer> intHandler = new MyHandler<>(1) { @Override public void handle() { // handling code... } }; MyHandler<? extends Integer> intHandler1 = new MyHandler<>(10) { @Override void handle() { // handling code... } }; MyHandler<?> handler = new MyHandler<>("One hundred") { @Override void handle() { // handling code... } }; }


Puede usarlo en java 9 Java9

MyHandler<Integer> intHandler = new MyHandler<>(1) { @Override public void handle() { // handling code... } };