Chris
Chris

Reputation: 125

Why JAVA can not compile when using generic type in interface

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

Answers (3)

Tamas Rev
Tamas Rev

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

TR4Android
TR4Android

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 ClassCastExceptions.

Upvotes: 3

Ray O&#39;Kalahjan
Ray O&#39;Kalahjan

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

Related Questions