Java泛型extends关键字设置边界的实现
|
本文主要介绍在泛型定义中的< >中的占位符如何配合extends关键字使用,形如<T extends Integer>。泛型定义存在于这三种形式中:泛型类、泛型接口、泛型方法。
接下来本文将以几个示例和具体分析来讲解剩下的知识点。 类型参数多边界的分析 此例中的泛型类,类型参数带有多个边界。讲下类的实际意义:Dimension代表物体的方位、HasColor代表物体的颜色、Weight代表物体的重量。
interface HasColor { java.awt.Color getColor(); }
class Colored<T extends HasColor> {
T item;
Colored(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 Dimension { public int x,y,z; }
// This won't work -- class must be first,then interfaces:
// class ColoredDimension<T extends HasColor & Dimension> { }
// Multiple bounds:
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(); }
// As with inheritance,you can have only one
// concrete class but multiple interfaces:
class Solid<T extends Dimension & 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 Dimension implements HasColor,Weight {
public java.awt.Color getColor() { return null; }
public int weight() { return 0; }
}
public class BasicBounds {
public static void main(String[] args) {
Solid<Bounded> solid = new Solid<Bounded>(new Bounded());
solid.color();
solid.getY();
solid.weight();
}
} ///:~
class derivedBounded extends Bounded {}
class Bounded1 extends Dimension implements HasColor,Weight {
public java.awt.Color getColor() { return null; }
public int weight() { return 0; }
}
public class BasicBounds {
public static void main(String[] args) {
//Solid<Bounded> solid = new Solid<Integer>(new derivedBounded());//给定的具体类型不符合边界
Solid<Bounded> solid1 = new Solid<Bounded>(new derivedBounded());//可以传递具体类型Bounded的子类
//Solid<Bounded> solid2 = new Solid<Bounded>(new Bounded1());//编译报错,因为泛型的静态类型检查
solid1.color();
solid1.getY();
solid1.weight();
}
} ///:~
根据上一条,那么new Solid<Integer>(new Bounded())这里指定的具体类型,由于和泛型类定义的T类型参数的要求extends Dimension & HasColor & Weight不相符,所以编译会报错;给构造器传值时,实参可以是Bounded的子类;一个同样继承了相同边界的类Bounded1 ,不能传递给构造器,因为类型已经被指定为Bounded了。 但是类型参数有多个边界时,java内部即java字节码到底是怎么处理的呢:
public static void main(java.lang.String[]);
Code:
0: new #2 // class Solid
3: dup
4: new #3 // class Bounded
7: dup
8: invokespecial #4 // Method Bounded."<init>":()V
11: invokespecial #5 // Method Solid."<init>":(LDimension;)V
14: astore_1
从Method Solid."<init>":(LDimension;)V可以看到,给Solid的构造器传递参数时,编译器认为这个形参是个Dimension,这就是编译器处理多个边界的方法,永远处理为第一个边界,即类型擦除为第一个边界。但剩下的两个边界怎么办呢,这里都被处理第一个边界了,我们再去看一下Solid.class的反编译代码就能找到答案:
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by Fernflower decompiler)
import java.awt.Color;
class Solid<T extends Dimension & HasColor & Weight> {
T item;
Solid(T item) {
this.item = item;
}
T getItem() {
return this.item;
}
Color color() {
return ((HasColor)this.item).getColor();//类型转换为其他边界,再调用方法
}
int getX() {
return this.item.x;
}
int getY() {
return this.item.y;
}
int getZ() {
return this.item.z;
}
int weight() {
return ((Weight)this.item).weight();//类型转换为其他边界,再调用方法
}
}
当调用的方法不属于第一个边界时,就进行类型转换处理为其他边界就行,反正T肯定是符合extends Dimension & HasColor & Weight的。 继承有边界要求的泛型类 通过观察上例可知,Colored、ColoredDimension、Solid这三个类在持有对象的方面有冗余的地方:都有同一个成员变量、同一个构造器、同一个get函数。而类型参数上,边界也是依次叠加的。同样,对于这些边界所带来的属性和方法,也是冗余的。
//HoldItem对边界T没有要求
class HoldItem<T> {
T item;
HoldItem(T item) { this.item = item; }
T getItem() { return item; }
}
//Colored2对边界T有HasColor的要求
class Colored2<T extends HasColor> extends HoldItem<T> {
Colored2(T item) { super(item); }
java.awt.Color color() { return item.getColor(); }
}
//ColoredDimension2对边界T有Dimension & HasColor的要求
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; }
}
//Solid2对边界T有Dimension & HasColor & Weight的要求,不过没有类继承它了
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<Bounded>(new Bounded());
solid2.color();
solid2.getY();
solid2.weight();
}
} ///:~
总结一下: 当一个泛型类继承另一个泛型类时(前者属于“定义泛型类”,后者属于“使用泛型类”),且使用了同一个类型参数时,定义泛型类的类型参数边界定义一定要小于等于使用的那个泛型类的边界要求。 泛型方法中的边界定义 (编辑:安卓应用网) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |
