泛型1
1. 泛型实例
例1. 泛型类示例。
package fanxing; public class Generic<T> { T ob; Generic(T o){ ob = o; } T get(){ return ob; } void showType(){ System.out.println("The Type of T is:"+ob.getClass().getName()); } }
用下面的程序使用泛型类:
package fanxing; public class demoGeneric { public static void main(String[] args) { Generic<Integer> iobj; iobj = new Generic<Integer>(100); iobj.showType(); int k = iobj.get(); System.out.println("k = "+k); Generic<String> sobj; sobj = new Generic<String>("Hello"); sobj.showType(); String s = sobj.get(); System.out.println("s = "+s); } }
程序的输出结果如下:
The Type of T is:java.lang.Integer k = 100 The Type of T is:java.lang.String s = Hello
注意:泛型类中的参数T不能使用在静态方法中。
2. 带有两个类型参数的泛型类
例2. 带两个类型参数的泛型。
package fanxing; public class twoGen<T,V> { private T obj1; private V obj2; twoGen(T o1, V o2){ obj1=o1; obj2=o2; } public void showType(){ System.out.println("The Type of T is:"+obj1.getClass().getName()); System.out.println("The Type of V is:"+obj2.getClass().getName()); } public T getObj1(){ return obj1; } public V getObj2(){ return obj2; } }
用下面的程序使用上面的泛型类:
package fanxing; public class simpGen { public static void main(String[] args) { twoGen<Integer,String> tg; tg = new twoGen<Integer,String>(100,"Hello"); tg.showType(); int k = tg.getObj1(); System.out.println("The value of obj1 is:"+k); String s = tg.getObj2(); System.out.println("The value of obj2 is:"+s); } }
程序的运行结果为:
The Type of T is:java.lang.Integer The Type of V is:java.lang.String The value of obj1 is:100 The value of obj2 is:Hello
3.有界类型
在指定一个类型参数时,,可以指定一个上界,声明所有的实际类型都必须是这样一个超类的直接或间接子类。语法形式如下:
class classname <T extends superclass>
例3. 有界类型程序示例。
package fanxing; public class stats<T extends Number> { T num[]; stats(T a[]){ num = a; } double average(){ double sum = 0; for(int i=0;i<num.length;i++) sum += num[i].doubleValue(); return sum/num.length; } }
下面演示了如何使用这个类:
package fanxing; public class demoBound { public static void main(String[] args) { Integer inum[] = {1,2,3,4,5}; stats<Integer> si = new stats<Integer>(inum); System.out.println("平均值为:"+si.average()); Double dnum[] = {1.1,2.2,3.3,4.4,5.5}; stats<Double> sd = new stats<Double>(dnum); System.out.println("平均值为:"+sd.average()); //如果像下面这样创建String类型的对象将无法编译通过 // String snum[] = {"1","2","3","4","5"}; // stats<String> ss = new stats<String>(snum); // System.out.println("平均值为:"+ss.average()); } }
程序的输出结果如下:
平均值为:3.0
平均值为:3.3
实际上,接口也可以用来作上界。比如:
class Stats<T extends Comparable>
注意:这里使用的关键字仍然是extends而非implments。
一个类型参数可以有多个限界,比如:
class Stats<T extends Comparable & Serializable>
注意:限界类型用“&”分割,因为逗号用来分割类型参数。在多个限界中,可以有多个接口,但最多只能有一个类。如果用一个类作为限界,则它必须是限界列表中的第一个。
4. 通配符参数
例4. 通配符的使用示例。
package fanxing; public class stats<T extends Number> { T num[]; stats(T a[]){ num = a; } double average(){ double sum = 0; for(int i=0;i<num.length;i++) sum += num[i].doubleValue(); return sum/num.length; } void doSomething(stats<?> s){ //这里使用了类型通配符 System.out.println(s.getClass().getName()); } }
如下程序调用上面的类:
package fanxing; public class demoBound { public static void main(String[] args) { Integer inum[] = {1,2,3,4,5}; stats<Integer> si = new stats<Integer>(inum); System.out.println("平均值为:"+si.average()); Double dnum[] = {1.1,2.2,3.3,4.4,5.5}; stats<Double> sd = new stats<Double>(dnum); System.out.println("平均值为:"+sd.average()); //如果像下面这样创建String类型的对象将无法编译通过 // String snum[] = {"1","2","3","4","5"}; // stats<String> ss = new stats<String>(snum); // System.out.println("平均值为:"+ss.average()); si.doSomething(sd); } }
程序运行结果如下:
平均值为:3.0 平均值为:3.3 fanxing.stats
void doSomething(stats<?> s){ //这里使用了类型通配符,其中通配符”?”有一个默认的上界,就是Number。如果想改变这个上界,也是可以的,比如:
stats<? extends Integer> s
但是不能写成这样的形式:
stats<? extends String> s
因为Integer是Number的子类,而String不是Number的子类。通配符无法将上界改变的超出泛型类声明时的上界范围。
注意:通配符是用来声明一个泛型类的变量的,而不能创建一个泛型类。比如下面这种写法是错误的:
class stats<? extends Number> {......}
5. 泛型方法
一个方法如果声明成泛型方法,那么它将拥有一个或多个类型参数,不过与泛型类不同,这些类型参数只能在它所修饰的泛型方法中使用。
创建一个泛型方法的常用形式如下:
[访问权限修饰符] [static] [final] <类型参数列表> 返回值类型 方法名([形式参数列表])
使用一个泛型方法通常有两种形式:
<对象名|类名>.<实际类型>方法名(实际参数列表);
和
<对象名|类名>.方法名(实际参数列表);
例5. 泛型方法使用示例。
package fanxing; public class demoGemMethods { public static <T> void showMsg(T ob, int n){ T localOb = ob; System.out.println(localOb.getClass().getName()); System.out.println(n); } public static <T> void showMsg(T ob){ System.out.println(ob.getClass().getName()); } public static void main(String[] args) { demoGemMethods.<Integer>showMsg(new Integer(100), 10); String s = "Hello"; showMsg(s); } }
程序运行结果如下:
java.lang.Integer 10 java.lang.String
6.泛型接口
泛型接口的定义与泛型类非常相似,它的声明形式如下:
interface 接口名<类型参数表>
例6. 泛型接口示例。
package fanxing; interface MinMax<T extends Comparable<T>> { T min(); T max(); }
实现这个接口:
package fanxing; public class MyClass<T extends Comparable<T>> implements MinMax<T> { T vals[]; MyClass(T t[]){ vals = t; } public T min(){ T val = vals[0]; for(int i=0;i<vals.length;i++) if(vals[i].compareTo(val)<0) val = vals[i]; return val; } public T max(){ T val = vals[0]; for(int i=0;i<vals.length;i++) if(vals[i].compareTo(val)>0) val = vals[i]; return val; } }
用程序测试MyClass的工作情况如下:
package fanxing; public class testMyClass { public static void main(String[] args) { Integer inum[] = {31, 35, 45, 12, 33, 78, 4}; Character chs[] = {'a', 'n', 'z', 'm', 'f'}; MyClass<Integer> mi = new MyClass<Integer>(inum); MyClass<Character> mc = new MyClass<Character>(chs); System.out.println("The min value in inum is:"+mi.min()); System.out.println("The max value in inum is:"+mi.max()); System.out.println("The min value in chs is:"+mc.min()); System.out.println("The max value in chs is:"+mc.max()); } }
程序运行结果如下:
The min value in inum is:4 The max value in inum is:78 The min value in chs is:a The max value in chs is:z