Concrete class doesn't compile with a generic identifier

Kieran :

I am puzzled by this compilation error. Consider the code snippet below, ConcreteClass1 has the following compilation error:

Error:(16, 28) java: incompatible types: java.util.Map java.lang.String,java.lang.String> cannot be converted to java.util.Map java.lang.String,java.lang.Object>

Yet ConcreteClass2 compiles successfully, simply because it extends AbstractClass rather than AbstractClass<Object>. Why is this?

abstract class AbstractClass<T extends Object> {

    void testGenerics(Map<String, Object> map) {
    }
}

class ConcreteClass1 extends AbstractClass<Object> {

    public void testGenerics() {
        Map<String, String> map = new HashMap<>();
        super.testGenerics(map);
    }
}

class ConcreteClass2 extends AbstractClass {

    public void testGenerics() {
        Map<String, String> map = new HashMap<>();
        super.testGenerics(map);
    }
}
Karol Dowbecki :

ConcreteClass2 is declared as a raw type, due to omitted generic inforamtion. As per official Raw Types tutorial:

Raw types show up in legacy code because lots of API classes (such as the Collections classes) were not generic prior to JDK 5.0. When using raw types, you essentially get pre-generics behavior

Because of above testGenerics(Map<String, Object> map) is interpreted as testGenerics(Map map) and it can be invoked with any Map object. All due to backward compatibility with pre Java 5 code.

You can take a look at JLS 4.8 Raw Types.

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=92424&siteId=1