本章前面简单地介绍过边界。边界使得你可以在用于泛型的参数类型上设置限制条件。尽管这使得你可以强制规定泛型可以应用的类型,但是其潜在的一个更重要的效果是你可以按照自己的边界类型来调用方法。
因为擦除移除了类型信息,所以,可以用无界泛型参数调用的方法只是那些可以用Object调用的方法。但是,如果能够将这个参数限制为某个类型子集,那么你就可以用这些类型子集来调用方法。为了执行这种限制,java泛型重用了extends关键字。对你来说有一点很重要,即要理解extends关键字在泛型边界上下文环境中和在普通情况下所具有的意义是完全不同的。下面的示例展示了边界的基本要素:
import java.awt.Color;
interface HasColor {
Color getColor();
}
class Colored<T extends HasColor> {
T item;
Colored(T item) {
this.item = item;
}
T getItem() {
return item;
}
Color color() {
return item.getColor();
}
}
/**
* 尺寸
*/
class Dimension {
public int x, y, z;
}
//class ColoredDimension<T extends HasColor& Dimension>{}
class ColoredDimension<T extends Dimension & HasColor> {
T item;
ColoredDimension(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();
}
/**
* 立体的
*/
class Solid<T extends Dimension & HasColor & Weight> {
T item;
Solid(T item) {
this.item = item;
}
T getItem() {
return item;
}
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 Dimension implements HasColor, Weight {
@Override
public int weight() {
return 0;
}
@Override
public Color getColor() {
return null;
}
}
public class BasicBounds {
public static void main(String[] args) {
Solid<Bounded> solid = new Solid<>(new Bounded());
solid.color();
solid.getY();
solid.weight();
}
}
你可能已经观察到了,BasicBounds.java看上去包含可以通过继承消除的冗余。下面,可以看到如何在继承的每个层次上添加边界限制:
import java.awt.Color;
class HoldItem<T> {
T item;
HoldItem(T item) {
this.item = item;
}
T getItem() {
return item;
}
}
class Colored2<T extends HasColor> extends HoldItem<T> {
Colored2(T item) {
super(item);
}
Color color() {
return item.getColor();
}
}
class ColoredDimension2<T extends Dimension & HasColor> extends Colored2<T> {
ColoredDimension2(T item) {
super(item);
}
int getX() {
return item.x;
}
int getY() {
return item.y;
}
int getZ() {
return item.z;
}
}
class Solid2<T extends Dimension & HasColor & Weight> extends ColoredDimension2<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直接持有一个对象,因此这种行为被继承到了Colored2中,它也要求其参数与HasColor一致。ColoredDimension2和Solid2进一步扩展了这个层次结构,并在每个层次上都添加了边界。现在这些方法被继承,因而不必在每个类中重复。下面是具有更多层次的示例:
import java.util.List;
/**
* 超级能力
*/
interface SuperPower {
}
/**
* 射线视觉
*/
interface XRayVision extends SuperPower {
void seeThroughWalls();
}
/**
* 超级听力
*/
interface SuperHearing extends SuperPower {
void hearSubtleBoises();
}
/**
* 超级嗅觉
*/
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.hearSubtleBoises();
}
void smell() {
power.trackBySmell();
}
}
class SuperHearSmell implements SuperHearing, SuperSmell {
@Override
public void trackBySmell() {
}
@Override
public void hearSubtleBoises() {
}
}
class DogBoy extends CanineHero<SuperHearSmell> {
DogBoy() {
super(new SuperHearSmell());
}
}
public class EpicBattle {
static <POWER extends SuperHearing> void useSuperHearing(SuperHero<POWER> hero) {
hero.getPower().hearSubtleBoises();
}
static <POWER extends SuperHearing & SuperSmell> void superFind(SuperHero<POWER> hero) {
hero.getPower().hearSubtleBoises();
hero.getPower().trackBySmell();
}
public static void main(String[] args) {
DogBoy dogBoy = new DogBoy();
useSuperHearing(dogBoy);
superFind(dogBoy);
List<? extends SuperHearing> audioBoys;
// List<? extends SuperHearing & SuperSmell> audioBoys;
}
}
注意,通配符被限制为单一边界。
1491





