💎一站式轻松地调用各大LLM模型接口,支持GPT4、智谱、星火、月之暗面及文生图 广告
## 边界 *边界*(bounds)在本章的前面进行了简要介绍。边界允许我们对泛型使用的参数类型施加约束。尽管这可以强制执行有关应用了泛型类型的规则,但潜在的更重要的效果是我们可以在绑定的类型中调用方法。 由于擦除会删除类型信息,因此唯一可用于无限制泛型参数的方法是那些 **Object** 可用的方法。但是,如果将该参数限制为某类型的子集,则可以调用该子集中的方法。为了应用约束,Java 泛型使用了 `extends` 关键字。 重要的是要理解,当用于限定泛型类型时,`extends` 的含义与通常的意义截然不同。此示例展示边界的基础应用: ```java // generics/BasicBounds.java interface HasColor { java.awt.Color getColor(); } class WithColor<T extends HasColor> { T item; WithColor(T item) { this.item = item; } T getItem() { return item; } // The bound allows you to call a method: java.awt.Color color() { return item.getColor(); } } class Coord { public int x, y, z; } // This fails. Class must be first, then interfaces: // class WithColorCoord<T extends HasColor & Coord> { // Multiple bounds: class WithColorCoord<T extends Coord & HasColor> { T item; WithColorCoord(T item) { this.item = item; } T getItem() { return item; } java.awt.Color color() { return item.getColor(); } int getX() { return item.x; } int getY() { return item.y; } int getZ() { return item.z; } } interface Weight { int weight(); } // As with inheritance, you can have only one // concrete class but multiple interfaces: class Solid<T extends Coord & HasColor & Weight> { T item; Solid(T item) { this.item = item; } T getItem() { return item; } java.awt.Color color() { return item.getColor(); } int getX() { return item.x; } int getY() { return item.y; } int getZ() { return item.z; } int weight() { return item.weight(); } } class Bounded extends Coord implements HasColor, Weight { @Override public java.awt.Color getColor() { return null; } @Override public int weight() { return 0; } } public class BasicBounds { public static void main(String[] args) { Solid<Bounded> solid = new Solid<>(new Bounded()); solid.color(); solid.getY(); solid.weight(); } } ``` 你可能会观察到 **BasicBounds.java** 中似乎包含一些冗余,它们可以通过继承来消除。在这里,每个继承级别还添加了边界约束: ```java // generics/InheritBounds.java class HoldItem<T> { T item; HoldItem(T item) { this.item = item; } T getItem() { return item; } } class WithColor2<T extends HasColor> extends HoldItem<T> { WithColor2(T item) { super(item); } java.awt.Color color() { return item.getColor(); } } class WithColorCoord2<T extends Coord & HasColor> extends WithColor2<T> { WithColorCoord2(T item) { super(item); } int getX() { return item.x; } int getY() { return item.y; } int getZ() { return item.z; } } class Solid2<T extends Coord & HasColor & Weight> extends WithColorCoord2<T> { Solid2(T item) { super(item); } int weight() { return item.weight(); } } public class InheritBounds { public static void main(String[] args) { Solid2<Bounded> solid2 = new Solid2<>(new Bounded()); solid2.color(); solid2.getY(); solid2.weight(); } } ``` **HoldItem** 拥有一个对象,因此此行为将继承到 **WithColor2** 中,这也需要其参数符合 **HasColor**。 **WithColorCoord2** 和 **Solid2** 进一步扩展了层次结构,并在每个级别添加了边界。现在,这些方法已被继承,并且在每个类中不再重复。 这是一个具有更多层次的示例: ```java // generics/EpicBattle.java // Bounds in Java generics import java.util.List; interface SuperPower { } interface XRayVision extends SuperPower { void seeThroughWalls(); } interface SuperHearing extends SuperPower { void hearSubtleNoises(); } interface SuperSmell extends SuperPower { void trackBySmell(); } class SuperHero<POWER extends SuperPower> { POWER power; SuperHero(POWER power) { this.power = power; } POWER getPower() { return power; } } class SuperSleuth<POWER extends XRayVision> extends SuperHero<POWER> { SuperSleuth(POWER power) { super(power); } void see() { power.seeThroughWalls(); } } class CanineHero<POWER extends SuperHearing & SuperSmell> extends SuperHero<POWER> { CanineHero(POWER power) { super(power); } void hear() { power.hearSubtleNoises(); } void smell() { power.trackBySmell(); } } class SuperHearSmell implements SuperHearing, SuperSmell { @Override public void hearSubtleNoises() { } @Override public void trackBySmell() { } } class DogPerson extends CanineHero<SuperHearSmell> { DogPerson() { super(new SuperHearSmell()); } } public class EpicBattle { // Bounds in generic methods: static <POWER extends SuperHearing> void useSuperHearing(SuperHero<POWER> hero) { hero.getPower().hearSubtleNoises(); } static <POWER extends SuperHearing & SuperSmell> void superFind(SuperHero<POWER> hero) { hero.getPower().hearSubtleNoises(); hero.getPower().trackBySmell(); } public static void main(String[] args) { DogPerson dogPerson = new DogPerson(); useSuperHearing(dogPerson); superFind(dogPerson); // You can do this: List<? extends SuperHearing> audioPeople; // But you can't do this: // List<? extends SuperHearing & SuperSmell> dogPs; } } ``` 接下来将要研究的通配符将会把范围限制在单个类型。