type parameter generic data java java-7 type-inference

parameter - type erasure java



¿Por qué no se pueden inferir los tipos de diamante en clases internas anónimas? (3)

En el JSR-334 :

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

Lo que supongo es que, como todos saben, la clase anónima conduce a una generación de su propio archivo de clase.

Imagino que el tipo genérico no existe dentro de estos archivos y que se reemplaza por el tipo efectivo (estático) (así declarado por el tipo explícito como <String> en el momento del objeto de declaración).

De hecho, el archivo correspondiente a una clase interna nunca se comparte en múltiples instancias diferentes de él, así que, ¿por qué molestarse con los genéricos en él? :).

Sería más difícil de lograr (y seguramente inútil) que el compilador fuerce una extensión (agregando un atributo especial para genéricos) a este tipo de archivos de clase.

En Java 7 y versiones posteriores, el diamante se puede usar para inferir tipos normalmente sin problemas:

List<String> list = new ArrayList<>();

Sin embargo, no puede para clases internas anónimas como esta:

List<String> st = new List<>() { //Doesn''t compile //Implementation here }

¿Por qué es esto? Lógicamente en este escenario, definitivamente puedo inferir el tipo como String . ¿Existe una razón lógica para esta decisión donde el tipo no se puede inferir en clases internas anónimas, o se omitió por otras razones?


En resumen, <> hace poco para inferir tipos, desactiva la advertencia que obtendría sin él.

EDITAR: Como @Natix señala que hace algunas comprobaciones.

List<Integer> ints = new ArrayList<>(); List<String> copy = new ArrayList<>(ints);

produce un error de compilación

Error:Error:line (42)error: incompatible types required: List<String> found: ArrayList<Integer>

Como puede ver, <> está tomando el tipo del argumento, no inferiendo el tipo del tipo de copy


Google rendimientos, después de omitir publicaciones de , http://mail.openjdk.java.net/pipermail/coin-dev/2011-June/003283.html

Supongo que es así, normalmente una clase anónima es una subclase concreta del tipo aparente

interface Foo<N extends Number> { void foo(N n); } Foo<Integer> foo = new Foo<Integer>(){ ... }

es implementado por

class AnonFoo_1 implements Foo<Integer>{ ... } Foo<Integer> foo = new AnonFoo_1();

Supongamos que permitimos la inferencia de diamante en clases anónimas, puede haber un caso complicado como

Foo<? extends Runnable> foo = new Foo<>(){ ... }

Las reglas de inferencia producen N=Number&Runnable ; Siguiendo el truco de implementación anterior, necesitamos

class AnonFoo_2 implements Foo<Number&Runnable>{ ... }

Eso no está permitido actualmente; el tipo arg para supertipo Foo debe ser un tipo "normal".

Sin embargo, la razón no es muy fuerte. Podemos inventar otros trucos de implementación para que funcione.

class AnonFoo<N extends Number&Runnable> implements Foo<N> { @Override public void foo(N n) { n.intValue(); n.run(); } } Foo<? extends Runnable> foo = new AnonFoo<>();

El compilador debería ser capaz de hacer el mismo truco.

En cualquier caso, al menos el compilador debe permitir la mayoría de los casos de uso que no impliquen "tipos innegables", como Foo<Integer> foo = new Foo<>(){...} Es una pena que estos sean comunes / simples. Los casos están prohibidos innecesariamente también.