2011-12-09 58 views
3

爲什麼在第二個示例中沒有任何編譯錯誤,但在第一個示例中存在以下編譯錯誤?與Java泛型和繼承相關的編譯錯誤

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

UPDATE:
我是否正確地理解,例如,在低於所有樹開始m 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> 
{} 

回答

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不是通用的,因此原始類型沒有問題。

+0

但ISomeInterface - 不是一個泛型類。爲什麼它不禁用所有與通用相關的東西?爲什麼ISomeBaseInterface 不會變成ISomeBaseInterface <>? –

+0

@Vladimir:原始類型是具有省略類型參數的泛型類型。非泛型類不是原始類型,因此它不具有原始類型的典型效果。 – axtavt

+0

這是正確的行爲嗎?如果SomeDerivedClass被用作原始類型,爲什麼需要在SomeDerivedClass中使用SomeAbstractClass 的擦除? –