泛型接口

  • 定义泛型接口
    在 JDK 1.5之后,不仅可以在接口上声明泛型,声明格式与之前类似,是咋接口名称后面加上< T>即可。格式如下:
【访问权限】 interface 接口名称<泛型标识>{}

下面利用以上定义一个泛型接口:
【定义一个泛型接口】

interface Info<T>{
    public T getVar();
}
  • 泛型接口实现的两种方式
    泛型接口定义完成之后,就要定义此接口的子类,定义泛型接口的子类有两种方式,一种是直接在子类后声明泛型,另一种是直接在子类实现的接口中明确的给出泛型类型。
    【定义子类方式-1】——在子类的定义上声明泛型类型
inteface Info<T>{
    public T getVar();
}
class InfoImpl<T> implements Info<T>
{
    private T var;
    public InfoImpl(T var){
        this.setVar(var);
    }
    public void setVar(T var){
        this.var=var;
    }
    public T getVar(){
        return this.var;
    }
}

以上程序泛型接口的子类声明了与接口中同样的泛型标识,使用以上子类的方式与前面的程序类似。
使用泛型接口的子类

public class GenericsDemo24
{
    public static void main(String args[]){
        Info<String> i=null;
        i=new InfoImpl<String>("张三");
        System.out.println("姓名:"+i.getVar());
    }
}

运行结果:

---------- java ----------
姓名:张三

以上程序不难理解,虽然指定了泛型,但是依然可以使用对象的多态性通过一个子类为接口实例化。
【定义子类方式-2】——直接在接口中指定具体类型

interface Info<T>{
    public T getVar();
};
class InfoImpl implements Info<String>
{
    private String var;
    public InfoImpl(String var){
        this.setVar(var);
    }
    public void setVar(String var){
        this.var=var;
    }
    public String getVar(){
        return this.var;
    }
};

以上程序泛型接口的子类正在实现接口时,直接在实现的接口处指定了具体的泛型类型String,这样在覆写Info接口中的getVar()方法是直接声明类型为String类型。
使用泛型接口的子类:

public class GenericsDemo25
{
    public static void main(String args[]){
        Info<String> i=null;
        i=new InfoImpl("张三");
        System.out.println("姓名:"+i.getVar());
    }
}

运行结果:

---------- java ----------
姓名:张三

泛型方法

前面学习的所有泛型操作都是将整个类进行泛型化,但同样也可以在类中定义泛型化的方法。泛型方法的定义与其所在的类是否是泛型类是否没有任何关系,所在的类可以是泛型类,也可以不是泛型类。

  • 定义泛型方法
    在方形方法中可以定义泛型参数,此时,参数的类型就是传入数据的类型,可以使用如下的格式定义泛型方法。
    【泛型方法的简单定义】
【访问权限】<泛型标识> 泛型标识 方法名称([泛型标识 参数名称])

【定义一个泛型方法】

class Demo
{
    public<T> T fun(T t){
        return t;
    } 
}
public class GenericsDemo26
{
    public static void main(String args[]){
        Demo d=new Demo();
        String str=d.fun("张三");
        int i=d.fun(30);
        System.out.println(str);
        System.out.println(i);
    }   
}

运行结果:

---------- java ----------
张三
30

以上程序的fun()方法是将接收到的参数直接返回,而且因为在方法接收参数中使用了泛型操作,所以此方法可以接收任意类型的数据,而且此方法的返回值类型将由泛型指定。

  • 通过泛型方法返回泛型类实例
    如果可以通过泛型方法返回一个泛型类的实例化对象,则必须在方法的返回类型声明处明确的指定泛型标识。
    【通过方法返回泛型类实例】
class Info<T extends Number>
{
    private T var;
    public T getVar(){
        return var;
    }
    public void setVar(T var){
        this.var=var;
    }
    public String toString(){
        return this.var.toString();
    }
}
public class GenericsDemo27
{
    public static void main(String args[]){
        Info<Integer> i=fun(30);
        System.out.println(i.getVar());
    }
    public static <T extends Number> Info<T> fun(T param){
        Info<T> temp =new Info<T>();
        temp.setVar(param);
        return temp;
    }
}

运行结果:

---------- java ----------
30

上面的代码中的fun()方法在static关键字处定义了“ < T extends Number>”的意思是,方法中传入或返回的泛型类型由调用方法时所设置的参数类型决定。

  • 使用泛型统一传入的参数类型
    如果现在一个方法要求传入的泛型对象的泛型类型一致,也可以通过泛型方法指定。
    【统一输入对象的泛型类型】
class Info<T>
{
    private T var;
    public T getVar(){
        return var;
    }
    public void setVar(T var){
        this.var=var;
    }
    public String toString(){
        return this.var.toString();
    }
}
public class GenericsDemo28
{
    public static void main(String args[]){
        Info<String> i1=new Info<String>();
        Info<String> i2=new Info<String>();
        i1.setVar("Hello");
        i2.setVar("张三");
        add(i1,i2);
    }
    public static <T>void add(Info<T> i1,Info<T> i2){
        System.out.println(i1.getVar()+" "+i2.getVar());
    }
}

运行结果:

---------- java ----------
Hello 张三

上面程序中add()方法中的两个Info对象的泛型类型必须一致。如果设置的类型不一致策在编译的时候会出现错误,有兴趣可以动手试一下。

泛型与子类继承的限制
一个类的子类可以通过对象的多态性为其父类实例化,但是在泛型操作中,子类类型是无法使用父类的泛型类型接收的,例如,Info < String>不能使用Info < Object>接收。