与java泛型和继承相关的编译错误

时间:2011-12-09 08:49:24

标签: java generics

为什么第二个示例中没有任何编译错误,但第一个示例中存在以下编译错误?

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

唯一的区别 - 类SomeDerivedClass在第二个示例中未参数化。

例1:
我在这个例子中是否正确理解

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>
{}

示例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>
{}

更新
我是否正确理解,在下面的示例中,从SomeDerivedClass开始的所有树都将用作原始类型?
SomeBaseClass的第一个参数是List的信息将丢失 这是对的吗?

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>
{}

1 个答案:

答案 0 :(得分:3)

简而言之,使用原始类型(即使用不带类型参数的泛型类型)会禁用其背后的所有通用相关内容。

通常通过以下示例演示:

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

你有类似的情况,但它与继承而不是成员访问有关。

以下是JLS 4.8 Raw Types的相关引用:

  

原始类型的超类(分别是超级接口)是其任何参数化调用的超类(超接口)的擦除。

在第一个示例中,SomeDerivedClass是通用的,SomeConcreteClass将其作为原始类型继承。因此,通过此继承分支继承的ISomeBaseInterface<Object>变为其擦除ISomeBaseInterface<>,但直接继承的ISomeInterface仍然继承ISomeBaseInterface<Object>。由于您无法使用不同的类型参数多次实现相同的通用接口,因此编译器会报告错误。

在第二个示例中,SomeDerivedClass不是通用的,因此原始类型没有问题。