初学者学Java(二十)

来源:互联网 发布:外国人怎么看中国 知乎 编辑:程序博客网 时间:2024/05/22 04:33

                   泛型(Generics)

        泛型是作为jdk5.0的新特性出现的,在没有泛型之前,我们使用集合类的时候,不管存的是什么类型,返回的都是Object类型,用的时候需要强制类型转换。但如果我们存的如果是String类型的变量,却强制类型转换为Integer类型,这样在编译的时候并不会报错,因为我们是将一个Object类型的转换为Integer类型,而系统在编译时并不知道我们存如的是String类型,但在执行的时候会出现异常。

为了解决这个问题我们引入了泛型。

              泛型的使用方法

1.规定数据类型,提高代码的安全性(以ArrayList为例)

在学泛型以前我们使用ArrayList会产生一个警告。

例:

package test;

import java.util.*;

public class GenericsTestOne {

    public static void main(String[]args) {

        List listOne = newArrayList();

    }

}

警告是这么写的:

         ArrayList 是原始类型。应该将对通用类型ArrayList<E> 的引用参数化

后面的<E>就是泛型的一种表现形式。

他说没有用泛型进行引用参数化,如果不进行参数化会引起什么错误呢。

下面我写这么几行代码:

listOne.add("冶近玮");

Integer int1 =(Integer)listOne.get(0);

这在编译的时候并不会报错,因为集合get()方法返回的是一个Object类型的,在编译的时候编译器并不知道我在内部存放的是一个String类的变量,所以这么写不会报错。但在执行的时候他就会知道内部是String类,所以会给我报一个异常,是这么写的:

 java.lang.ClassCastException: java.lang.Stringcannot be cast to java.lang.Integer

也就是说String类型的变量不能转换成Integer类型。

而我们的泛型就是解决这个问题的,如果使用泛型,只要代码在编译时没有出现警告,就不会遇到运行时ClassCastException。下面我们看看泛型怎么使用,和使用后的效果。还是上面这个程序我只修改 一行:

 List<String> listOne = new ArrayList<String>();

这时在我们把String强制转换为Integer的那行,他就不会不痛不痒的给个警告,而会直接给出错误:

不能从 String 强制类型转换为Integer

所以泛型可以提高代码的安全性。

2.泛型可以提高代码的质量

在以前,我们想要写一个类,类中有一个字符串变量,get(),set(),构造方法。还有一个类,类中有一个Integer变量,get(),set(),构造方法。只能这么写:

class MyTestOne

{

    private String string1;

    public String getString1() {

        return string1;

    }

    public void setString1(String string1) {

        this.string1 = string1;

    }

    public MyTestOne(String string1)

    {

        this.string1 = string1;

    }

}

class MyTestTwo

{

    private Integer integer1;

    public Integer getString1() {

        return integer1;

    }

    public void setString1(Integer integer1) {

        this.integer1 = integer1;

    }

    public MyTestTwo(Integer integer1)

    {

        this.integer1= integer1;

    }

}

这只是两个类呢,要是20个呢?还不得累死。但是我们学了泛型就可以这么写:

class MyTest<T>

{

    private T o1;

    public T getString1() {

        return o1;

    }

    public void setString1(T o1) {

        this.o1 = o1;

    }

    public MyTest(To1)

    {

        this.o1 = o1;

    }

}

如果你想要一个String型的你就这么声明:

MyTest<String>myTest1 =new MyTest<String>("冶近玮");

如果你想要一个Integer型的你就这么声明:

 

MyTest<Integer> myTest2= new MyTest<Integer>(new Integer(1));

效果和上面写两个类效果是一样的,来20个类,不过就是多20个声明罢了,会大大的减少代码量。

而且在定义泛型类别时,预设可以使用任何的类型来实例化泛型类型中的类型,但是如果想要限制使用泛型类别时,只能用某个特定类型或者是其子类型才能实例化该类型时,可以在定义类型时,使用extends关键字指定这个类型必须是继承某个类,或者实现某个接口。其实我们上面写的<T>是等价于下面这个式子。

<T       extends         Object>

就算两个类名相同的变量,泛型不同也不能互相赋值,如上例的myTest1和myTest2就不能互相赋值,否则报错。

关于泛型我就说这些了。

 

 

 

 

 

原创粉丝点击