The Java™ Tutorials — Generics :Generics, Inheritance, and Subtypes 泛型,继承和子类型

本文深入探讨了Java泛型中的继承概念,解释了为何泛型类的子类型关系不同于普通类,并介绍了如何正确使用泛型类及其子类。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

The Java™ Tutorials — Generics :Generics, Inheritance, and Subtypes 泛型,继承和子类型

原文地址:https://docs.oracle.com/javase/tutorial/java/generics/inheritance.html

关键点

泛型间父子关系:

全文翻译

As you already know, it is possible to assign an object of one type to an object of another type provided that the types are compatible. For example, you can assign an Integer to an Object, since Object is one of Integer’s supertypes:

正如你所知道的那样,当类型兼容时,你就可以把一个类型的对象赋值给另一类型。例如,你可以把一个Integer赋值给一个Object,因为Object是Integer的一个超类。

Object someObject = new Object();
Integer someInteger = new Integer(10);
someObject = someInteger;   // OK

In object-oriented terminology, this is called an “is a” relationship. Since an Integer is a kind of Object, the assignment is allowed. But Integer is also a kind of Number, so the following code is valid as well:

在面向对象术语中,这是一种名为“是一个”的关系。由于Integer是一种Object,因此这样的赋值就是被允许的。但是Integer也是一种Number,所以下面的代码也是有效的:

public void someMethod(Number n) { /* ... */ }

someMethod(new Integer(10));   // OK
someMethod(new Double(10.1));   // OK

The same is also true with generics. You can perform a generic type invocation, passing Number as its type argument, and any subsequent invocation of add will be allowed if the argument is compatible with Number:

对于泛型而言也是同理。你可以通过传入一个Number作为类型变量来调用一个泛型。并且如果其类型和Number是兼容的话,之后关于add()方法的调用也都是允许的:

Box<Number> box = new Box<Number>();
box.add(new Integer(10));   // OK
box.add(new Double(10.1));  // OK

Now consider the following method:

现在看下下面的方法:

public void boxTest(Box<Number> n) { /* ... */ }

What type of argument does it accept? By looking at its signature, you can see that it accepts a single argument whose type is Box<Number>. But what does that mean? Are you allowed to pass in Box<Integer> or Box<Double>, as you might expect? The answer is “no”, because Box<Integer> and Box<Double> are not subtypes ofBox<Number>.

哪种类型的参数可以被接受呢?通过观察它的签名,你可以发现,它会接受一个单独的参数,且其类型为Box<Number>。但这个参数是啥意思呢?你会像你自己可能期望的那样被允许传入一个Box<Integer>或者Box<Double>嘛?答案是否定的,因为这两个类型并非为Box<Number>的子类。

This is a common misunderstanding when it comes to programming with generics, but it is an important concept to learn.

当面对泛型问题时,这里存在一个普遍的误解。然而这个被误解的概念对于学习Java却十分重要。

Box<Integer>is not a subtype of Box<Number> even though Integer is a subtype of Number.

Box<Integer>并不是Box<Number>的一个子类,虽然Integer确实是Number的一个子类。

Note: Given two concrete types A and B (for example, Number and Integer), MyClass<A> has no relationship to MyClass<B>, regardless of whether or not A and B are related. The common parent of MyClass<A> andMyClass<B> is Object.

注意:假设这里给出两个具体的类型A和B(例如,Number和Integer),MyClass<A>MyClass<B>并没有关系,无论A和B是否有关系。两者的共同父类为Object。

For information on how to create a subtype-like relationship between two generic classes when the type parameters are related, see Wildcards and Subtyping.

关于当类型参数有关联时,如何在两个泛型类中创建一种像父子类样的关系的更多信息,请参考《通配符》和《子类》的章节。

Generic Classes and Subtyping 泛型类和泛型子类

You can subtype a generic class or interface by extending or implementing it. The relationship between the type parameters of one class or interface and the type parameters of another are determined by the extends and implements clauses.

你可以通过扩展一个泛型类,或者实现一个泛型接口来创建泛型子类。一个类或接口的泛型参数和另一个类或接口的泛型参数间的关系是由子句extends和implements决定的。

Using the Collections classes as an example, ArrayList<E> implements List<E>, and List<E> extends Collection<E>. So ArrayList<String> is a subtype of List<String>, which is a subtype ofCollection<String>. So long as you do not vary the type argument, the subtyping relationship is preserved between the types.

以集合类为例,ArrayList<E>实现了List<E>接口,而这个接口扩展自Collection<E>。所以,ArrayList<String>List<String>的子类,而List<String>却又是Collection<String>的子类。只要你不改动类型变量,这种类型间子类关系就会保持不变。

Now imagine we want to define our own list interface, PayloadList, that associates an optional value of generic type P with each element. Its declaration might look like:

现在想象下我们希望定义我们自己list接口PayloadList。这个接口对每个元素关联了泛型P的一个可替换值。它的声明也许会像这样:

 interface PayloadList<E,P> extends List<E> {
  void setPayload(int index, P val);
  ...
} 

The following parameterizations of PayloadList are subtypes of List<String>:

以下参数化的PayloadList都是List<String>的子类:

  • PayloadList<String,String>
  • PayloadList<String,Integer>
  • PayloadList<String,Exception>

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值