首页 > 代码库 > java泛型

java泛型

什么是泛型?

泛型是程序设计语言的一种特性。允许程序员在强类型程序设计语言中编写代码时定义一些可变部分,那些部分在使用前必须作出指明。泛型是Java SE 1.5的新特性,泛型的本质是参数化类型,也就是说所操作的数据类型被指定为一个参数。这种参数类型可以用在类、接口和方法的创建中,分别称为泛型类、泛型接口、泛型方法。

我们为什么要使用泛型?

我们在编写程序时,经常遇到两个模块的功能非常相似,只是一个是处理int数据,另一个是处理string数据,或者其他自定义的数据类型,但我们没有办法,只能分别写多个方法处理每个数据类型,因为方法的参数类型不同。然而,泛型可以很轻松的解决这个问题。

用一个小小的例子简单看看:

public class Point <T>{    private T var;    public T getVar(){        return var;    }    public void setVar(T var){        this.var=var;    }}
public class test {    public static void main(String[] args) {        Point<String> p1 = new Point<String>();        p1.setVar(30 + "");        Point<Integer> p2 = new Point<Integer>();        p2.setVar(30);        System.out.println(p1.getVar());        System.out.println(p2.getVar());    }}

运行结果如下:

从代码中可以很明显的看出泛型的优势。

同时,泛型可以使程序操作更加安全,可以避免发生类转换异常。当然还可以提高代码重用率。

泛型的基本应用

 泛型的定义:

类定义:

  【访问权限】 class 类名称 <泛型类型标识1,泛型类型标识2,……,泛型类型标识n>{

  【访问权限】 泛型类型标识 变量名称;

  【访问权限】 泛型类型标识 方法名称(){};

  【访问权限】 返回值类型声明 方法名称(泛型类型标识 变量名称){};

}

对象定义:

类名称<具体类> 对象名称=new 类名称<具体类>();

注意:

  1. 在上面的例子中,Point类中使用了"<T>",T表示此类型是由外部调用本类时指定的,使用任意字母均可,如<A>、<Y>都可以,为了突出type(表示类型)才使用的T。
  2. 另外,泛型是无法指定基本数据类型的,必须设置成一个类,因此在设置一个数字时就必须使用包装类。
  3. 如果设置的内容与泛型所指定的类型不一致,则会在编译时出错。
  4. 可以在声明类时指定多个泛型类型。如class A<K,V>{}
  5. 在泛型应用中最好在声明类对象时指定好其内部的数据类型,如Info<String>,否则在使用时会出现不安全操作的警告信息。(不影响程序运行)

通配符的使用:

在泛型类的操作中,在进行引用传递时,泛型类型必须匹配才可以传递。

例如将上面的例子改成:

public class test {    public static void main(String[] args) {        Point<String> p1 = new Point<String>();        p1.setVar(30 + "");        fun(p1);    }    private static void fun(Point<Object> p1) {        System.out.println(""+p1.getVar());            }}

会有如下的错误提示:

另外,我们还可以直接去掉<Object>,可正常运行。但是,不指定泛型类型不符合习惯,因此引入了通配符“?”,表示接收此类型的任意泛型对象。修改如下:

public class test {    public static void main(String[] args) {        Point<String> p1 = new Point<String>();        p1.setVar(30 + "");        fun(p1);    }    private static void fun(Point<?> p1) {        System.out.println(""+p1.getVar());            }}

注意:如果使用"?"接收泛型对象时,则不能设置被泛型指定的内容。如:Point<?> p1 = new Point<String>();

受限泛型:

泛型上限使用extends关键字声明,表示泛型的类型可能是所指定的类型或者是此类型的子类。

泛型下限使用super进行声明,表示泛型的类型可能是所指定的类型,或者是此类的父类,或是Object类。

具体格式:

设置上限:(声明对象)类名称<? extends 类> 对象名称      (定义类)[访问权限] 类名称<泛型标识 extends 类>

设置下限:(声明对象)类名称<? super 类> 对象名称    (定义类)[访问权限] 类名称<泛型标识 super 类>

同样以最上面的例子做修改:

public class test {    public static void main(String[] args) {        Point<Integer> p1 = new Point<Integer>();        p1.setVar(30 );        fun(p1);    }    private static void fun(Point<? extends Number> p1) {        System.out.println(""+p1.getVar());            }}

运行结果如下:(可正常运行)

注意:

一个类的子类可以通过对象的多态性为其父类实例化,但是在泛型操作中,子类的泛型类型是无法使用父类的泛型类型接收的,

如:

public static void main(String[] args) {        Point<Integer> p1 = new Point<Integer>();        Point<Number> p2 = new Point<Number>();        p2=p1;    }

编译时会出错:

这里为什么不能向上转型呢?

如果将子类泛型变为父类泛型,则表示扩大了子类的内容。打个比方:p1和p2由于类型的不同,p2相当于商场的全部商品,p1相当于个人购买的商品,如果p2=p1就相当于在个人购买商品中加入了商城的全部商品,这是基本不可能的。

泛型接口:

格式:【访问权限】 interface 接口名称 <泛型标识>

interface info<T>{    public T getVar();}

泛型接口的实现方式有两种:

  1. 在子类的定义上声明泛型类型
  2. 直接在接口中指定具体类型

下面分别实现(第一种)

interface info<T>{    public T getVar();}class Point <T> implements info <T>{    private T var;    public Point(T var){        this.setVar(var);    }    public T getVar(){        return var;    }    public void setVar(T var){        this.var=var;    }}
public class test {    public static void main(String[] args) {        info<String> i=null;        i=new Point<String>("hehe");        System.out.println(""+i.getVar());            }}

运行结果:

(第二种)

interface info<T>{    public T getVar();}class Point implements info<String>{    private String var;    public Point(String var){        this.setVar(var);    }    public String getVar(){        return var;    }    public void setVar(String var){        this.var=var;    }}
public class test {    public static void main(String[] args) {        info<String> i=null;        i=new Point("hehe");        System.out.println(""+i.getVar());            }}

运行结果:

 

泛型方法

泛型方法的定义与其所在的类是否是泛型类是没有任何关系的。

定义:【访问权限】<泛型标识> 泛型标识 方法名称(【泛型标识 参数名称】)

如:public<T> T fun(T t){ return t;}

个人感觉泛型方法的使用与一般方法的使用并无太大的区别。

 

泛型的嵌套

 简单的讲就是在一个类的泛型中指定另外一个类的泛型。用一个简单的实例就能明白了。

class info<T,V>{    private T var;    private V value;    public info(T var,V vanue){        this.setVar(var);        this.setValue(vanue);    }    public T getVar(){        return var;    }    public void setVar(T var){        this.var=var;    }    public V getValue(){        return value;    }    public void setValue(V value){        this.value=http://www.mamicode.com/value;    }}class Demo <S>{    private S info;    public Demo(S info){        this.setInfo(info);    }    public S getVar(){        return info;    }    public void setInfo(S info){        this.info=info;    }}
public class test {    public static void main(String[] args) {        Demo<info<String,Integer>> d=null;//将info作为泛型类型        info<String,Integer> i=null;//info要指定两个两个泛型类型        i=new info<String,Integer>("123",456);        d=new Demo<info<String,Integer>>(i);//在demo类中设置info类对象        System.out.println(""+d.getVar().getVar());        System.out.println(""+d.getVar().getValue());            }}

运行结果: