I have some Guice binding code using generics that compiles and functions fine from Eclipse's compiler, but not from the Java (command-line) compiler. I upgraded to the latest (1.7.0_01) Java SDK but still get the following error.
[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
Relevant code:
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);
I know the answer is working and accepted but I believe the downcast is not the perfect solution. Also my code cleanup remove the obsolete down cast...
1) the reason eclipse and command line does not yield the same problem is because of eclipse settings. Go to preferences - java - compiler - Errors/Warnings and set Generic types (unchecked generic type operation) to warning. Then you will detect the same problem if you remove the
@SuppressWarnings("unchecked")
2) I had a similar issue and a friend show me another solution. To fix the code properly (without the down cast) just change the CategoryDataProvider.class to this:
Then put back the
@SuppressWarnings("unchecked")
Do yourself a favor and do an upcast followed by a downcast:
The issue is that
CDP.class
is of typeClass<CDP>
,CDP
being a raw type. While a parameterized typeC<T1,...,Tn>
is the subtype of the raw typeC
(§4.10.2), the inverse is not true:C
is not a subtype ofC<T1,...,Tn>
. This only appears to be true due to unchecked conversion (§5.1.9). This is causing your issue: You expectCDP
to "extend" (as in the upper bound ofClass<? extends ...>
)LADP<Row<? extends DI>>
. This is not the case because type argument containment (§4.5.1.1) is defined over subtyping and does not consider unchecked conversion.(Or to cut to the chase: javac has got this one right.)