Volodymyr Bezuglyy
Volodymyr Bezuglyy

Reputation: 16795

Compilation error related to java generics and inheritance

Why there are no any compilation errors in the second example but there is following compilation error in the first example?

SomeConcreateClass.java:1: ISomeBaseInterface cannot be inherited with different arguments: <java.lang.Object> and <>
public class SomeConcreateClass
       ^
1 error

The only difference - class SomeDerivedClass is not parameterized in the second example.

Example1:
Do I understand correctly that in this example

public class SomeConcreateClass
   extends SomeDerivedClass
   implements ISomeInterface
{}

class SomeDerivedClass<T> /* <-------*/
    extends SomeAbstractClass<Object>
    implements ISomeInterface
{}

abstract class SomeAbstractClass<T> 
   implements ISomeBaseInterface<T>
{}

interface ISomeInterface extends ISomeBaseInterface<Object> 
{}

interface ISomeBaseInterface<T>
{}

Example 2:

public class SomeConcreateClass
   extends SomeDerivedClass
   implements ISomeInterface
{}

class SomeDerivedClass /* <-------*/
    extends SomeAbstractClass<Object>
    implements ISomeInterface
{}

abstract class SomeAbstractClass<T> 
   implements ISomeBaseInterface<T>
{}

interface ISomeInterface extends ISomeBaseInterface<Object> 
{}

interface ISomeBaseInterface<T>
{}

UPDATE:
Do I understand correctly that in example below all tree starting from SomeDerivedClass will be used as raw type?
Information that first parameter for SomeBaseClass is List will be lost.
Is it correct?

import java.util.List;

public class SomeConcreateClass
   extends SomeDerivedClass
   implements ISomeInterface
{
    public static void main(String[] args) {
        SomeConcreateClass c = new SomeConcreateClass();
        List lst = c.getT(); //Type mismatch: cannot convert from Object to List
    }
}

class SomeDerivedClass<T>
   extends SomeBaseClass<List, T> /* <----- */
   implements ISomeInterface
{}

class SomeBaseClass<T, M>
   implements ISomeBaseInterface<T>
{
   public T getT(){return null;}
}

interface ISomeInterface extends ISomeBaseInterface<List> 
{}

interface ISomeBaseInterface<T>
{}

Upvotes: 3

Views: 945

Answers (1)

axtavt
axtavt

Reputation: 242686

In short, use of raw type (i. e. use of generic type without type parameter) disables all generic-related stuff behind it.

It's usually demonstrated by the following example:

class Foo<T> { public List<String> m() { ... } }

String s1 = new Foo<Object>().m().get(0); // Compiles
String s2 = new Foo().m().get(0); // Cannot cast Object to String

You have the similar situation, but it's related to inheritance rather than member access.

Here is a relevant quote from JLS 4.8 Raw Types:

The superclasses (respectively, superinterfaces) of a raw type are the erasures of the superclasses (superinterfaces) of any of its parameterized invocations.

In your first example, SomeDerivedClass is generic, and SomeConcreteClass inherits it as a raw type. Thus, ISomeBaseInterface<Object> inherited through this branch of inheritance turns into its erasure ISomeBaseInterface<>, but ISomeInterface inherited directly still inherits ISomeBaseInterface<Object>. Since you cannot implement the same generic interface many times with different type parameters, compiler reports an error.

In the second example, SomeDerivedClass is not generic, therefore there are no problems with raw types.

Upvotes: 3

Related Questions