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

 

你可能感兴趣的:(泛型)