2011-11-14 13 views
9

Tengo un código de enlace de Guice usando genéricos que compila y funciona bien desde el compilador de Eclipse, pero no desde el compilador de Java (línea de comandos). Me actualicé al último SDK de Java (1.7.0_01) pero sigo recibiendo el siguiente error.Java Generics Error: tipos inconvertibles del compilador de línea de comandos

[error] ...\BindCategorySelectorActivity.java:42: error: inconvertible types 
[error]         (Class<? extends ListAdapterDataProvider<Row<? extends DatabaseItem>>>) CategoryDataProvider.class); 
[error]                               ^
[error] required: Class<? extends ListAdapterDataProvider<Row<? extends DatabaseItem>>> 
[error] found: Class<CategoryDataProvider> 
[error] 1 error 
[error] {file:/.../compile:compile: javac returned nonzero exit code 

código relevante:

public interface Category extends DatabaseItem {} 
public class CategoryDataProvider implements 
ListAdapterDataProvider<Row<Category>> {} 
public class BindListViewHandlerWithSpecificProvider extends AbstractModule { 
    public BindListViewHandlerWithSpecificProvider(
    Class<? extends ListAdapterDataProvider<Row<? extends DatabaseItem>>> 
     dataProviderClass) {} 
} 

@SuppressWarnings("unchecked") 
// Error happens here: 
final BindListViewHandlerWithSpecificProvider 
bindListViewHandlerWithSpecificProvider = 
    new BindListViewHandlerWithSpecificProvider(
    (Class<? extends ListAdapterDataProvider<Row<? extends DatabaseItem>>>) 
    CategoryDataProvider.class); 

Respuesta

6

Hágase un favor y hacer una conversión hacia arriba seguido de un abatido:

Class<...> foo = (Class<...>)(Object)MyClass.class; 

La cuestión es que CDP.class es de tipo Class<CDP>, CDP ser una tipo sin procesar Mientras que un tipo parametrizado C<T1,...,Tn> es el subtipo del tipo sin procesar C (§4.10.2), el inverso no es verdadero: C no es un subtipo de C<T1,...,Tn>. Esto solo parece ser cierto debido a la conversión no verificada (§5.1.9). Esto está causando su problema: espera CDP para "extender" (como en el límite superior de Class<? extends ...>) LADP<Row<? extends DI>>. Este no es el caso porque la contención de tipo de argumento (§4.5.1.1) se define sobre la subtipificación y no considera la conversión no verificada.

(o para cortar por lo sano: javac tiene este derecho.)

+0

Bueno, se las arregló para compilar, pero no estoy seguro de si agregar el lanzamiento adicional a Object simplemente enmascaró el problema. Guice se bloquea con una excepción de puntero nulo al intentar enlazar. La línea que informa es acceder al 'bindListViewHandlerWithSpecificProvider'. Y recuerde, este código idéntico se compila y ejecuta sin errores cuando se compila dentro de Eclipse. –

+1

Debo admitir que es un comportamiento curioso. Hacer el lanzamiento adicional a Object no hace más que engañar a javac de 'sideCast'ing. Deberías terminar con el mismo programa. –

+0

¿Está familiarizado con el soporte agregado de Guice para genéricos y si habría un mejor mecanismo para pasar tipos parametrizados? ¿Alguna idea de si Scala proporciona una mejor asistencia para pasar tipos parametrizados? –

1

sé la respuesta está trabajando y acepté pero creo que el abatido no es la solución perfecta. También la limpieza de mi código elimina el molde obsoleto ...

1) la razón por la que el eclipse y la línea de comando no producen el mismo problema es debido a la configuración de eclipse. Vaya a preferencias - compilador de Java - Errores/advertencias y establezca los tipos genéricos (operación de tipo genérico sin marcar) como advertencia. A continuación, detectará el mismo problema si elimina el @SuppressWarnings("unchecked")

2) Tuve un problema similar y un amigo me mostró otra solución. Para corregir el código correctamente (sin el molde hacia abajo) acaba de cambiar los CategoryDataProvider.class a esto:

new CategoryDataProvider<Row<DatabaseItem>>().getClass() 

A continuación, volver a poner la @SuppressWarnings("unchecked")

+0

Este método podría funcionar solo si la clase (en este caso, CategoryDataProvider) tiene un constructor predeterminado. En casos más complicados, este método puede requerir que haga una gran cantidad de preparaciones e inicializaciones, solo para recuperar la clase. –