泛型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

 

posted @ 2015-01-21 15:59  ~风轻云淡~  阅读(296)  评论(0编辑  收藏  举报