Java泛型的使用

来源:互联网 发布:论文引用格式网络文章 编辑:程序博客网 时间:2024/06/07 07:24

在通常的时候,一般的类和方法,只能使用具体的类型:要么是基本类型,要么是自定义的类型,如果可以应用于多种类型的代码,那么就要用到泛型.

泛型的概念:参数化类型 使代码可以应用于多种类型。

1.1简单的泛型

   有许多的原因促成了泛型的出现,而最引人注目的一个原因就是为了创造容器类.容器就事存放要使用对象的地方,数组也是如此,不过与简单的数组相比容器显得更灵活一些,具有更多的功能。

class holder2{private Object a;public holder2(Object a){this.a=a;}public void set (Object a){this.a=a;}public Object get(){return a;}}public class main {public static void main(String[] args) {// TODO 自动生成方法存根holder2 h2=new holder2(new String());String str=(String)h2.get();h2.set(1);System.out.println(h2.get().toString());//hoder2可以存储任何类型对象}}

与其使用object,我们程序员更新欢暂时不指定类型,而是稍后再决定具体使用什么类型,要达到这个目的,需要使用类型参数,用尖括号括住,放在类名后面,然后再使用这个类的时候,再用实际的类型替换此类参型参数。

2.2利用泛型return返回多个对象

   仅一次方法调用就可以返回多个对象,你应该经常需要这样的功能吧?可是return语句只允许返回单个对象,但是有了泛型咱们就能够一次性的解决这个问题,以后再也不用在这个问题上浪费时间了。

   这个概念称为元祖(tuple),它是将一组对象直接打包存储于其中的一个单一对象,这个容器对象允许读取器中元素,但是不允许向其中存放新的对象(这个概念也称为数据传递对象或信使)

class TwoTuple<A,B>{public final A first;public final B second;public TwoTuple(A a,B b){first =a;second=b;}public String toString(){return "("+first+"."+second+")";}}public class tempalte{public static void main(String[] args){TwoTuple<String, Integer> tt=new TwoTuple<String,Integer>("hello",100);System.out.println(tt);}}

我们利用构造器捕获了要存储的对象,而ToString事一个便利函数,用来显示列表中的值。

你也许会想,这不是违反了Java编程的安全性能原则了吗?first和second应该生命为private,然后提供GetFirst(),GetSecond()之类的访问方法才对啊。客户端程序可以读取first和 second对象,然后可以随心所欲地使用这两个对象,但是却无法将其的值赋予first或second.因为final声明了他们,而且这种格式更简洁了.

2.3 泛型方法

   到目前为止我们看到的泛型,都是应用于整个类上。但同样可以在类中包含参数化的方法,而这个方法所在的类可以是泛型类,也可以不是泛型类,也就是说,是否拥有泛型方法,与其所在的类是否是泛型没有关系.

   泛型方法使得该方法能够独立于类而产生变化。以下是一个基本的指导原则:无论何时,只要你能做到,你就应该尽量使用泛型方法,也就是说,如果使用泛型方法可以取代将整个类泛型化,那么就应该只使用泛型方法,因为它可以使事情更清楚明白。另外对于一个static的方法而言,无法访问泛型的类型参数,所以,如果static方法需要使用泛型能力,就必须使其成为泛型方法.

   要定义泛型方法,只需将泛型参数列表置于返回值之前

public class GenericMethods {/** * @param args */public <T> void f(T x){System.out.println(x.getClass().getName());}public static void main(String[] args) {// TODO 自动生成方法存根GenericMethods gm=new GenericMethods();gm.f(" ");gm.f(11);gm.f(11.1);}}Output :        java.lang.Stringjava.lang.Integerjava.lang.Double

总结: GenericMethods类并不是参数化的,尽管这个类和其内部的方法可以被同时参数化,但是在这个例子中,只有方法f()拥有类型参数。这是由该方法的返回类型前面的类型参数列表指明的。

注意: 当使用泛型类时,必须在创建对象的事后指定类型参数的值,而使用泛型方法的时候,通常不必知名参数类型,因为编译器会为我们找出具体的类型。这称为类型参数推断。因此,我们可以像调用普通方法一样调用f(),而且就好象是f()被无限次地重载。它甚至可以接受本类做为它自己的类型参数.

2.3.1 多参数泛型方法

修改GenericMethods类,使f()方法可以接受三个类型各不相同的参数.

public class GenericMethods {/** * @param args */public <T,F,X> void f(T t,F f,X x){System.out.println(t.getClass().getName());System.out.println(f.getClass().getName());System.out.println(x.getClass().getName());}public static void main(String[] args) {// TODO 自动生成方法存根GenericMethods gm=new GenericMethods();//gm.f(" ",1,"aa");//gm.f(11,1,"bb");//gm.f(11.1,"aa");gm.f(" ", "a", 11);gm.f(" ", "a", 11.1);}}Output :java.lang.Stringjava.lang.Stringjava.lang.Integerjava.lang.Stringjava.lang.Stringjava.lang.Double

2.4深入泛型

当你开始更深入地钻研泛型时,会发现有大量的东西最初看起来没有什么意义,例如:尽管可以声明ArrayList.class ,但是不能声明成为ArrayList<Integer>.class

import java.util.ArrayList;public class My {public static void main(String[] args){Class c1=new ArrayList<String>().getClass();Class c2=new ArrayList<Integer>().getClass();System.out.println(c1==c2);}}Output “true”

//类Class 的实例表示当前运行的Java应用程序中的类和接口。每个数组也属于一个class,被映射为一个Class对象,被所有有着相同元素和数字大小的数组共享。简单Java类型(booleanbytecharshort、 intlongfloatdouble)和关键字void也能表示为Class对象。

ArrayList<String>,和ArrayList<Integer>很容易被认为是不同的类型,不同的类型在行为方面肯定不同,例如,如果尝试着将一个Integer放入ArrayList<String>,所得到的行为(将失败)与把一个Integer放入ArrayList<Integer>(将成功)所得到的行为完全不同。但是上面的程序会认为它们是相同的类型.

残酷的现实就是如此,再泛型的代码内部,无法获得任何有关泛型参数类型的信息。

Java泛型事使用擦除来实现的,这意味当你在使用泛型时,任何具体的类型信息都被擦除了,你唯一知道的就是你在使用一个对象,因此List<String>和List<Integer>在运行时事实上相同的类型,这两种形式都被擦除称它们“原生”类型,即List.

2.4 泛型出现的各类问题

2.41任何基本类型都不能作为类型参数.

不能创建ArratList<int>之类的,解决之道是使用基本类型的包装器以及Java SE5的自动包装机制,并将基本类型int应用于这个容器,那么你将发现自动包装机制将自动地实现int到Integer的双向转换,所以  这几乎就像有一个ArratList<int>一样.

2.42 重载

public class My<W,T> {

void f(List<t> v);

void f(List<w> v);

}

由于擦除的原因,重载方法将产生相同的类型签名.

于此不同的是,当被擦除的参数不能产生唯一的参数列表,必须提供明显有区别的方法名。

public class My<W,T> {

void f1(List<t> v);

void f2(List<w> v);

 

}



0 0
原创粉丝点击