Java泛型类型参数的界限
来源:互联网 发布:淘宝店代运营可靠吗 编辑:程序博客网 时间:2024/06/07 21:11
作用
1. 限制类型参数的类型
如要定义一个类IntegerPair来存取元素类型为Integer的对偶,此类可写成如下的形式:
public class IntegerPair<T extends Integer>{ public IntegerPair() { first = null; second = null; } public IntegerPair(T first, T second) { this.first = first; this.second = second; } public T getFirst() { return first; } public T getSecond() { return second; } public void setFirst(T newValue) { first = newValue; } public void setSecond(T newValue) { second = newValue; } private T first; private T second;}
类型参数后的extends关键字表示T 的上界为Integer类型,编译器在类型擦除阶段会将T替换成Integer,生成的字节码如下所示:
Compiled from "IntegerPair.java"public class generic.bound.IntegerPair<T extends java.lang.Integer> { public generic.bound.IntegerPair(); descriptor: ()V Code: 0: aload_0 1: invokespecial #1 // Method java/lang/Object."<init>":()V 4: aload_0 5: aconst_null 6: putfield #2 // Field first:Ljava/lang/Integer; 9: aload_0 10: aconst_null 11: putfield #3 // Field second:Ljava/lang/Integer; 14: return public generic.bound.IntegerPair(T, T); descriptor: (Ljava/lang/Integer;Ljava/lang/Integer;)V Code: 0: aload_0 1: invokespecial #1 // Method java/lang/Object."<init>":()V 4: aload_0 5: aload_1 6: putfield #2 // Field first:Ljava/lang/Integer; 9: aload_0 10: aload_2 11: putfield #3 // Field second:Ljava/lang/Integer; 14: return public T getFirst(); descriptor: ()Ljava/lang/Integer; Code: 0: aload_0 1: getfield #2 // Field first:Ljava/lang/Integer; 4: areturn public T getSecond(); descriptor: ()Ljava/lang/Integer; Code: 0: aload_0 1: getfield #3 // Field second:Ljava/lang/Integer; 4: areturn public void setFirst(T); descriptor: (Ljava/lang/Integer;)V Code: 0: aload_0 1: aload_1 2: putfield #2 // Field first:Ljava/lang/Integer; 5: return public void setSecond(T); descriptor: (Ljava/lang/Integer;)V Code: 0: aload_0 1: aload_1 2: putfield #3 // Field second:Ljava/lang/Integer; 5: return}
可见,IntegerPair支持类型为Integer及其子类型的元素,故BoundTest不会通过编译。
public class BoundTest { public static void main(String[] args) { IntegerPair integerPair = new IntegerPair(); integerPair.setFirst("text"); }}
由于IntegerPar的类型参数T的界限为Integer,IntegerPair setFirst的签名为(Ljava/lang/Integer;)V,故编译BoundTest时会报错,因为integerPar setFisrt传入的是String类型:
BoundTest.java:12: error: incompatible types: String cannot be converted to Integer integerPair.setFirst("text"); ^Note: Some messages have been simplified; recompile with -Xdiags:verbose to get full output1 error
2.实现通用算法
可以通过类型参数调用界限的方法,如NaturalNumber所示:
public class NaturalNumber<T extends Integer> { private T n; public NaturalNumber(T n) { this.n = n; } public boolean isEven() { return n.intValue() % 2 == 0; } // ...}
由于类型参数T的界限为Integer,故可在T上调用Integer的方法,如initValue. 能调用界限的方法是实现通用算法的关键。考虑求某个列表中大于某个元素的算法:
public static <T> int countGreaterThan(T[] anArray, T elem) { int count = 0; for (T e : anArray) if (e > elem) // compiler error ++count; return count;}
由于运算符>只能在基础数据类型如short, int, long, double, float, byte和char上进行操作,无法对Object进行>操作,故编译器会报错:
GenericAlgorithm.java:19: error: bad operand types for binary operator '>' if (e > elem) // compiler error ^ first type: T second type: T where T is a type-variable: T extends Object declared in method <T>countGreaterThan(T[],T)1 error
这个问题会导致countGreaterThan方法不通用。给类型参数加上一个界限,可以很好的解决这个问题:
public interface Comparable<T> { public int compareTo(T o);}
新的通用算法如下:
public static <T extends Comparable<T>> int countGreaterThan(T[] anArray, T elem) { int count = 0; for (T e : anArray) if (e.compareTo(elem) > 0) ++count; return count;}
多界限
一个类型参数可有多个界限,表达方式如下:
<T extends B1 & B2 & B3>
类型变量T的类型为界限列表中任一类型的子类.zhu’ru注意:如类型参数中的某个界限为类,必须放在界限列表中的第一个位置,如MultiBounds.java所示:
public class MultiBounds { static class A { public void a() { } } interface B { void b(); } interface C { void c(); } static class D <T extends A & B & C> { public void d(T t) { t.a(); t.b(); t.c(); } } public static void main(String[] args) { D d = new D(); d.d(new A()); }}
若D中类型参数的界限类表声明成如下形式,B为接口,类A放在界限列表的第二个位置,故编译器将会报错:
D <T extends B & A & C>
小结
类型参数的界限可以用来限制类型变量的类型,是实现通用算法的关键;类型变量可以有多个界限。
- Java泛型类型参数的界限
- 数据结构--递归 协变 泛型方法 类型界限
- 严格限定泛型类型采用多重界限
- Java获取泛型的类型参数
- 深入java 泛型通配符和上下界限定
- Java获取泛型参数的类型的方法
- Java获取泛型参数的类型的方法 .
- JAVA 泛型的类型参数需要注意的地方
- Java获取泛型参数的类型的方法
- java泛型学习3之类型参数的限制
- java 通过反射获得泛型的实际类型参数
- java中通过反射获取泛型的参数类型
- Java泛型-获得泛型的实际参数类型
- java泛型通配符和类型参数的范围
- Java 泛型的类型与参数传递
- Java 运行时如何获取泛型参数的类型
- Java 运行时如何获取泛型参数的类型
- Java 运行时如何获取泛型参数的类型
- 1410501139蒋云超
- 多模式匹配算法:AC算法、WM算法
- Touch事件机制
- Microsoft Orleans框架
- 设计模式(3)——工厂方法模式
- Java泛型类型参数的界限
- EF 错误LINQ to Entities 不识别方法“Int32 ToInt32(System.String)
- 位域
- ThingWorx : 3、为Thing添加valueStream(web显示曲线做准备)
- RxJava的初学随笔(二)
- 设计模式(4)——抽象工厂模式
- Android Studio :Error:(1, 0) Plugin is too old, please update to a more recent version, or set AND……
- iOS开发--根据label内容动态设定label大小
- 链表的反转