Java对泛型的支持(一) - 基本语法

题外话:前几天我的笔记本电脑硬盘坏了,本子送到售后进行维修,需要2到3个工作日才能搞定。。现在木有本本用了,无奈就借了女朋友的本子先用着了。。现装的JDK,UltraEdit。。所以下面的图片中编译器的报错信息就变成了中文。。哎,脆弱的硬盘啊。。。哭


Java在J2SE 5.0后开始增加了泛型(Generics)功能,并且许多API都根据这个新的功能被重新改写了,例如List、Map、Set等与数据结构相关的类。如果我们不想使用泛型功能,也可以用J2SE 1.4或以前的版本的语法来使用这些类,但编译的时候就会出现一些警告。如果对泛型了解不足,那么就会完全不知编译器所云。因此,了解或学会使用泛型是十分必要的。


1、在没有泛型之前

先来看2个类:

IntegetTest : 

class IntegerTest
{
    private Integer integer;
    
    public void setObj(Integer integer)
    {
        this.integer = integer;
    }

    public Integer getObj()
    {
        return integer;
    }
}

BooleanTest :

class BooleanTest
{
    private Boolean bool;
    
    public void setObj(Boolean bool)
    {
        this.bool = bool;
    }
    
    public Boolean getObj()
    {
        return bool;
    }
}

通过观察我们发现,这两个类除了Boolean和Integer这两个关键字不同外,其它的代码都相同。如此相似的类如果我们必须要写两份代码就难免有些冗杂。我们都知道,Object类是所有类的父类,因此用Object类来实现泛型或许是个不错的解决方案。如:

class ObjectTest
{
    private Object obj;
    
    public void setObj(Object obj)
    {
        this.obj = obj;
    }
    
    public Object getObj()
    {
        return obj;
    }
    
}
于是我们在使用ObjectTest这个类时就需要编写如下代码:

ObjectTest obj = new ObjectTest();
        obj.setObj(new Integer(100)); //传递一个Integer对象的引用
        
        //由于getObj()方法返回的是一个Object类型对象的引用,因此需要强制转换为Integer
        Integer I = (Integer)obj.getObj();
可以看出,如果要使用getObj()方法得到我们想要的对象,那么就必须进行一次强制类型转换才能满足我们的需求。但问题就出在这里。很多时候,我们往往会忘记进行强制转换,这时候编译器就会报错:

因此这就需要开发人员在写代码的时候要额外注意。在没有泛型之前,所有存入List, Map, Set窗口中的实例都会失去其类型信息,当我们要取出数据进行使用时,就必须再手动强制转换回它们原来的类型。如果我们忘记了它们是什么类型的对象,那就费时了。。慢慢拉上去翻前面的代码吧。。。


2、定义泛型类

为了解决传统的泛型设计用Object定义类所带来的种种问题(如类型丢失、程序员忘记了转换类型、必须将其转换为原来的类型才能调用相应的方法),Java在J2SE 5.0之后提出了针对泛型设计的解决方案。

如:下面的代码用泛型类取代了Object :

// 在类名后面,使用<T>来声明一个类型持有者(Holder)
public class Demo<T>
{
    private T obj;
    
    public void setObj(T obj)
    {
        this.obj = obj;
    }
    public T getObj()
    {
        return obj;
    }
}

使用泛型定义类时,可以用<T>来声明一个类型持有者(Holder)。然后就可以用 T 这个名称作为类型来声明成员、参数或返回值类型。在声明对象时,用尖括号一并指定泛型类类型持有者T的真正类型。如:

Demo<Integer> obj = new Demo<Integer>();

这样,在调用getObj()方法时,返回的就会是一个我们在尖括号内所指定的Integet对象,而不是Object了,因此也就不必再进行类型转换了:

obj.setObj(new Integer(100));
        Integer I = obj.getObj(); //无需强制转换


如果我们使用泛型类声明对象的时候没有为它指定类型,那么编译器默认会使用Object类型。这样的话我们就得又要像之前那样进行类型转换了。


3、几个泛型的小例子

我们可以在定义泛型类时,同时声明多个类型持有者,如:

class Test<T1,T2> //声明了两个Holder 
{
    private T1 obj1;
    private T2 obj2;
    
    public Test(T1 obj1,T2 obj2)
    {
        this.obj1 = obj1;
        this.obj2 = obj2;
    }
}

也可以声明数组,如:

class TestArray<T>
{
    // 声明T类型的数组
    private T[] objs;
    
    public TestArray(T[] objs)
    {
        this.objs = objs;
    }
}
但要注意的是,不允许使用泛型来建立数组的实例,如下面的操作是错误的:

class TestArray<T>
{
    // 声明T类型的数组
    private T[] objs = new T[10]; //Error
    
    public TestArray(T[] objs)
    {
        this.objs = objs;
    }
}


了解了以上知识,我们就可以在实际中应用泛型类了。在下一节中我们会介绍Java中泛型的高级语法。



posted @ 2013-03-25 21:48  司青  阅读(1001)  评论(0编辑  收藏  举报