泛型
就本质而已,术语“泛型”的意思是参数化类型。参数化类型很重要,因为使用该特性创建的类、接口以及方法,可以作为参数指定所操作数据的类型。例如,使用泛型可以创建自动操作不用类型数据的类。操作参数化类型的类、接口或方法被称为泛型,例如泛型类或泛型方法。
尽管泛型和C++中的模板很类似,但是它们不是一回事。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
| class Gen<T> { T ob; Gen(T o) { this.ob = o; } T GetOb() { return ob; } void ShowType() { System.out.println("Type of T is " + ob.getClass().getName()); } }
public class LearnGen1 { public static void main(String args[]) { Gen<Integer> iOb = new Gen<Integer>(88); Gen<String> iOb2 = new Gen<>("88"); iOb.ShowType(); iOb2.ShowType(); } }
|
泛型只使用引用类型
当声明泛型实例时,传递过来的类型参数必须是引用类型。不能使用基本类型,如int或char。当前,不能使用基本类型基本类型不是一个严重的限制,因为可以使用类型封装器将基本类型。
1 2
| Gen<int> iOb1 = new Gen<int>(88); Gen<Integer> iOb2 = new Gen<Integer>(88);
|
基于不同类型参数的泛型类型是不同的
对特定版本的泛型类型的引用和同一个泛型类型的其他版本不是类型兼容的。
1 2 3 4
| Gen<Integer> iOb1 = new Gen<Integer>(88); Gen<String> iOb2 = new Gen<>("88");
iOb2 = iOb1;
|
使用通配符参数
类型安全虽然有用,但有时可能会影响权威可以接受的结构。
对于没使用通配符参数的泛型接口,只有当其他对象的类型和调用对象的类型相同才能工作,这样就无法得到通用的泛型化的解决方案。
为了创建泛型化的方法,必须使用Java泛型的另一个特性:通配符(wildcard)参数。通配符参数由“?”指定,表示未知类型。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51
| class Stats<T extends Number> { T[] nums; Stats(T[] o) { this.nums = o; } double average() { double sum = 0.0; for(int i = 0; i < nums.length; ++i) { sum += nums[i].doubleValue(); } return sum / this.nums.length; } boolean sameAvg1(Stats<T> ob) { return average() == ob.average(); } boolean sameAvg2(Stats<?> ob) { return average() == ob.average(); } boolean sameAvg3(Stats<? extends Integer> ob) { return average() == ob.average(); } }
public class LearnGen2 { public static void main(String args[]) { Integer inums[] = {1, 2, 3, 4, 5}; Double dnums[] = {1.1, 2.2, 3.3, 4.4, 5.5}; Stats<Integer> iob = new Stats<>(inums); Stats<Double> dob = new Stats<>(dnums); iob.sameAvg1(dob); iob.sameAvg3(dob); iob.sameAvg2(dob); } }
|
泛型构造函数
可以将构造函数泛型化,即使它们的类不是泛型类。
1 2 3 4 5 6 7 8 9
| class Gen { private double val; <T extends Number>Gen(T arg) { val = arg.doubleValue(); } }
|
泛型接口
泛型接口的定义和泛型类相似。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57
| interface MinMax<T extends Comparable<T>> { T min(); T max(); }
class MyClass<T extends Comparable<T>> implements MinMax<T> { T[] vals; MyClass(T[] o) { this.vals = o; } public T min() { T v = vals[0]; for(int i = 1; i < vals.length; ++i) { if(vals[i].compareTo(v) < 0) { v = vals[i]; } } return v; } public T max() { T v = vals[0]; for(int i = 1; i < vals.length; ++i) { if(vals[i].compareTo(v) > 0) { v = vals[i]; } } return v; } }
public class LearnGen3 { public static void main(String args[]) { Integer inums[] = {3, 6, 2, 8, 6}; Character chs[] = { 'b', 'r', 'p', 'w' }; MyClass<Integer> iob = new MyClass<Integer>(inums); MyClass<Character> cob = new MyClass<Character>(chs); System.out.println(iob.max()); System.out.println(cob.min()); } }
|
泛型超类
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
| class Gen4<T> { T ob; Gen4(T o) { this.ob = o; } T GetOb() { return this.ob; } }
class Gen42<T,V> extends Gen4<T> { V ob2; Gen42(T o, V o2) { super(o); this.ob2 = o2; } V GetOb2() { return this.ob2; } }
|
对泛型异常的限制
泛型类不能扩展Throwable,这意味着不能创建泛型异常类。