在Java中总是使用“extends”而不是“implements”来定义类型参数的边界是否有特殊的原因?
例如:
public interface C {}
public class A<B implements C>{}
是禁止的,但是
public class A<B extends C>{}
是正确的。原因是什么?
在Java中总是使用“extends”而不是“implements”来定义类型参数的边界是否有特殊的原因?
例如:
public interface C {}
public class A<B implements C>{}
是禁止的,但是
public class A<B extends C>{}
是正确的。原因是什么?
当前回答
基类型可能是一个泛型参数,因此实际类型可能是一个类的接口。考虑:
class MyGen<T, U extends T> {
此外,从客户端代码的角度来看,接口几乎与类难以区分,而对于子类型来说,它很重要。
其他回答
在泛型约束语言中,类是“实现”还是“扩展”在语义上没有区别。约束的可能性是“extends”和“super”——也就是说,这个类是否可以赋值给另一个类(extends),或者这个类是否可以从那个类(super)赋值。
可能是因为对于双方(B和C)来说,只有类型是相关的,而不是实现。 在你的例子中
public class A<B extends C>{}
B也可以是一个接口。"extends"用于定义子接口和子类。
interface IntfSub extends IntfSuper {}
class ClzSub extends ClzSuper {}
我通常认为“Sub扩展Super”是“Sub类似于Super,但具有额外的功能”,而“Clz实现Intf”是“Clz是Intf的实现”。在您的示例中,这将匹配:B类似于C,但具有额外的功能。这里相关的是功能,而不是实现。
我们习惯了
class ClassTypeA implements InterfaceTypeA {}
class ClassTypeB extends ClassTypeA {}
任何对这些规则的轻微偏离都会让我们感到困惑。
类型绑定的语法定义为
TypeBound:
extends TypeVariable
extends ClassOrInterfaceType {AdditionalBound}
(JLS 12 > 4.4。输入变量>类型)
如果我们要改变它,我们肯定会添加工具的情况
TypeBound:
extends TypeVariable
extends ClassType {AdditionalBound}
implements InterfaceType {AdditionalBound}
最后得到两个处理相同的子句
ClassOrInterfaceType:
ClassType
InterfaceType
(jls 12 > 4.3.;引用类型和值> ClassOrInterfaceType
除了我们还需要注意工具之外,这将使事情更加复杂。
我相信这就是为什么使用extends ClassOrInterfaceType而不是extends ClassType和实现InterfaceType的主要原因——在复杂的概念中保持简单。问题是我们没有合适的词来同时涵盖扩展和实现,我们肯定不想介绍一个。
<T为ClassTypeA> <T是InterfaceTypeA>
尽管extends与接口一起使用会带来一些混乱,但它是一个更广泛的术语,可以用来描述这两种情况。尝试将您的思想调整到扩展类型的概念上(而不是扩展类,而不是实现接口)。你用另一个类型来限制一个类型参数,这个类型实际上是什么并不重要。重要的是它是它的上界,它是它的超类型。
下面是一个更复杂的例子,说明在哪里允许扩展,以及可能需要什么:
public class A<T1 extends Comparable<T1>>
实际上,在接口上使用generic时,关键字也是extends。下面是代码示例:
有2个类实现Greeting接口:
interface Greeting {
void sayHello();
}
class Dog implements Greeting {
@Override
public void sayHello() {
System.out.println("Greeting from Dog: Hello ");
}
}
class Cat implements Greeting {
@Override
public void sayHello() {
System.out.println("Greeting from Cat: Hello ");
}
}
测试代码:
@Test
public void testGeneric() {
Collection<? extends Greeting> animals;
List<Dog> dogs = Arrays.asList(new Dog(), new Dog(), new Dog());
List<Cat> cats = Arrays.asList(new Cat(), new Cat(), new Cat());
animals = dogs;
for(Greeting g: animals) g.sayHello();
animals = cats;
for(Greeting g: animals) g.sayHello();
}