初学者学Java(二十)
泛型(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就不能互相赋值,否则报错。
关于泛型我就说这些了。