最后一行有什么问题?
interface I1<T>{}
class Class1 implements I1{}
class Class2 extends Class1 implements I1{} //valid
class Class3 implements I1<Number>{}
class Class4 extends Class3 implements I1<Number>{} //valid
class Class5 implements I1<Number>{}
class Class6 extends Class5 implements I1<Integer>{} //not valid
class Class7 implements I1{}
class Class8 extends Class7 implements I1<Number>{} // not valid
class Class9 implements I1<Number>{}
class Class10 extends Class9 implements I1{} // not valid !!!
为什么我不能这样做?
我在书中看到了,但没有解释这件事 - 仅供参考。
P.S。
例外文字:
java: GenericsTest.I1 cannot be inherited with different arguments:
<java.lang.Integer> and <java.lang.Number>
答案 0 :(得分:7)
理解这一点有两点:
I1<Number>
和I1<Integer>
是不同的类型。在大多数情况下,它们是无关的,尽管Integer扩展了数字。现在,不允许的是实现两次接口,其中接口的泛型类型不同。
例如,不允许这样做:
class NotAllowed implements I1<String>, I1<Integer> {}
I1
的类型在运行时被删除,因此您无法执行此操作。在运行时,I1<String>
和I1<Integer>
之间并没有真正的区别。它们都只是I1
。
不允许使用Class5
和Class6
的示例,原因与上述NotAllowed
不允许相同。它实现了两次相同的接口,但具有不同的泛型类型。
如果允许,那将是矛盾的,因为例如给出以下内容:
interface Face<T> {
public void method(T t);
}
如果我然后用不同的类型实现这两次,那就意味着必须有两个一般类型的method
实现:
class Implementation
implements Face<String>, Face<Integer> {
@Override
public void method(String s) {}
@Override
public void method(Integer i) {}
}
这是矛盾的,因为擦除还要求method
的两个实现在运行时都会变得相同。
答案 1 :(得分:2)
class Class1 implements I1{}
class Class2 extends Class1 implements I1{}
这一点很明显,这意味着Class2实现了I1 {}。它通过说implements I1{}
明确地做到了,但也通过扩展Class1
来隐式地实现,它也实现了I1{}
。没有问题,因为它们都实现了相同的界面,它没有含糊不清。
class Class3 implements I1<Number>{}
class Class4 extends Class3 implements I1<Number>{}
这与上面的风格相同。它说Class4
实现I1<Number>
。它如上所述隐式和明确地指定。但它并不含糊,它是I1<Number>
当然,它是多余的,因为它同时使用两种方式来定义Class4
实现I1<Number>
。你可以做class Class4 extends Class3
而且它完全一样。
现在有了这个不同之处:
class Class5 implements I1<Number>{}
class Class6 extends Class5 implements I1<Integer>{}
它说Class6
正在实施I1<Integer>
(明确)和I1<Number>
(隐式地通过扩展Class5
)。它不可能在同一时间。想象一下,例如I1有一个方法:public X something()
。 I1<Number>
中的签名为public Number something()
,而I1<Integer>
中的签名为public Integer something()
。这将导致重复的方法。因此它无效。如果实现通用接口,则无论泛型类型如何,都只能实现一次。
我希望这有助于说明它无效的原因。
修改强>
首先,要了解I1
在语义上与I1<Object>
相同。
然后,了解I1<A>
与I1<B>
不同
另外,要了解所有无效示例都可以汇总(上面解释的原因):
class X implements I1<A>, I1<B>
为什么这个无效?因为它可能会在签名中产生歧义。如果I1
看起来像这样:
public interface I1<T> {
public T something();
}
然后X
必须看起来像:
class X implements I1<A>, I1<B> {
public A something() { return null; }
public B something() { return null; }
}
现在,如果我这样做了:
X x = new X();
x.something();
这两种方法中的哪一种是调用?你无法分辨,因为它含糊不清。 Java语言不会让您有机会定义不明确的API。因此,您无法同时实施I1<A>
和I1<B>
。
答案 2 :(得分:0)
因为Type Erasure实现一个具有两个不同通用参数的接口是不可能的。