Reputation: 125
Hello I have a problem using generic types in java. The actual problem is that when I am using generic type on a method declaration is working fine. Then if I a add a generic type to the interface declaration the code does not compile. Following is the working code:
public interface IRuntimeConvert {
public <T> T convertInstanceOfObject(String o, Class<T> clazz);
}
public class RuntimeConvertImpl implements IRuntimeConvert {
private final Map<String, Object> hashMap;
public RuntimeConvertImpl(Map<String, Object> hashMap) {
this.hashMap = hashMap;
}
@Override
public <T> T convertInstanceOfObject(String o, Class<T> clazz) {
try {
return clazz.cast(hashMap.get(o));
} catch (ClassCastException e) {
return null;
}
}
}
public static void main(String[] args) {
Map<String, Object> hashMap = new HashMap<>();
hashMap.put("s", "string");
hashMap.put("i", 0);
hashMap.put("l", 0L);
IRuntimeConvert rtConvert = new RuntimeConvertImpl(hashMap);
String s = rtConvert.convertInstanceOfObject("s", String.class);
System.out.println(s);
Integer i = rtConvert.convertInstanceOfObject("i", Integer.class);
System.out.println(i);
Long l = rtConvert.convertInstanceOfObject("l", Long.class);
System.out.println(l);
}
The above code is compiling. When I made the following changes the code is not compilable.
public interface IRuntimeConvert<S> {
public <T> T convertInstanceOfObject(String o, Class<T> clazz);
public S getSomething(S s);
}
public class RuntimeConvertImpl implements IRuntimeConvert<Object> {
private final Map<String, Object> hashMap;
public RuntimeConvertImpl(Map<String, Object> hashMap) {
this.hashMap = hashMap;
}
@Override
public <T> T convertInstanceOfObject(String o, Class<T> clazz) {
try {
return clazz.cast(hashMap.get(o));
} catch (ClassCastException e) {
return null;
}
}
@Override
public Object getSomething(Object s) {
throw new UnsupportedOperationException("Not supported yet.");
}
}
After the above changes in the main class I encouted a type cast error for each invocation of the method rtConvert.convertInstanceOfObject("s", String.class) with error message :
Incompatible types: Object cannot be converted to String.
If I try to run the main I get: Exception in thread "main" java.lang.RuntimeException: Uncompilable source code - incompatible types: java.lang.Object cannot be converted to java.lang.String
Upvotes: 3
Views: 422
Reputation: 7166
I cannot code the java language specification for you. I simply draw some conclusions.
If you change one line in main()
:
IRuntimeConvert<?> rtConvert = new RuntimeConvertImpl(hashMap);
// type ^^^^
Then the main()
will compile. So, apparently, javac
needs all the generics to be defined for the actual object type. Then it can deal with the method-level generic parameters.
Upvotes: 2
Reputation: 3246
This happens because you have specified the generic type in your implementation to be Object
with the following line:
public class RuntimeConvertImpl implements IRuntimeConvert<Object> {
As such, a call to getSomething
will always have to return an Object
. However, since String
is a subclass of Object
, this can not be automatically cast to a String
, you'd have to do something like:
String s = (String) rtConvert.getSomething();
Note that this does not guarantee type safety and may lead to ClassCastException
s.
Upvotes: 3
Reputation: 161
It may be an issue with Java trying to infere generic types. It's solved if you specify the generic type of the rtConvert
variable in the main method: IRuntimeConvert<Object> rtConvert
, instead of just IRuntimeConvert rtConvert
.
By default, I always try to specify the generic types of variables.
Upvotes: 1