I've got "incompatible types" compiler error in condition not yet discussed in stackoverflow (eg Why won't this generic java code compile? ).
My expectation is simple - I'm calling a templated method which does not use any 'generic' classes from containing class, therefore it should extract types of template parameters from method arguments and this should compile in all cases - but I get "incompatible types" compiler error.
I've noticed strange way to fix the problem - adding " < ? extends Data > " to generic datatype in method arguments. How does it change compiler logic?
In my understanding - there should be no difference because (1) DataContainer class' template parameters are not used in method call and (2) restriction " < TData extends Data > " already defines minimal base object class - Data - and therefore it should be automatically assumed when compiling template without arguments.
public void processData(DataContainer<? extends Data> c) {
(explicit type casting can be used, but i believe it is redundant here)
DummyContextClass dcc = (DummyContextClass)c.getContext(DummyContextClass.class);
Code for copy/paste
public class Test {
public static class Data {
}
public static class DataContainer<TData extends Data> {
public final TData Data;
private final Map<String, Object> contexts = new HashMap<>();
public DataContainer(TData data) {
Data = data;
}
public <T> T getContext(Class<T> type) {
return (T)contexts.get(type.getName());
}
public <T> void setContext(Class<T> type, T context) {
contexts.put(type.getName(), context);
}
}
public static class DummyContextClass {
}
public void processData(DataContainer c) {
c.setContext(DummyContextClass.class, new DummyContextClass());
// error: incompatible types: Object cannot be converted to DummyContextClass
DummyContextClass dcc = c.getContext(DummyContextClass.class);
}
}
The problem has nothing (much) to do with your generic methods.
Your problem is you are using a raw type as the parameter of your method:
public void processData(DataContainer c) { // Oops! DataContainer is a raw type
You should use a parameter with DataContainer
:
public void processData(DataContainer<? extends Data> c) {
When you leave off the type of a generic class, you have what is called a raw type, and (due to compatibility requirements with old java versions), all generic information is stripped off the class . That (amongst other things) changes all return types that are declared as generic types into Object
, so for compilation purposes, your method now looks like:
public Object getContext(Class type) {
...hence your error.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.