一、什么是泛型
泛型主要是指“在程序编码中包含类型参数的类型”。在JAVA中主要是指在定义类、接口或者方法时可以为之指定特定的类型参数。
二、泛型的主要作用。
JAVA中的泛型的主要作用可以归结为以下几点:
1、加强类型安全及减少类转换的次数;
在JAVA支持泛型以前,加入你将一个对象仍进一个集合,那么这个集合将不再记
得这个对象的类型,如果你要使用原来的类型,你必须进行强制类型转换,我们称这是类型不安全的。有了泛型以后,集合 将 能记住元素的类型。
public class Test
{
public static void main(String[] args){
List strList=new ArrayList(); //本想创建一个只能放字符串的集合
strList.add("chen");
strList.add("yuyue");
strList.add(1013); //1
for(Sting string:strList){
String str=(String)string; //此处我们可以发现每次必须强制转换,而且由于1处的代码还会出现
//ClassCastException
}
}
}
2、使某个方法适合更多的数据类型;
三、泛型入门
1.泛型语法
List<String> strList=new ArrayList<string>(); //定义了一个只能放字符串的集合,取出集合元素时不再需要强制转换
List<String> strlist=new ArrayList<>() //JDK 7 以后上面的声明可以简写为左边的形式
2.定义泛型类、接口
public class Person<T>{
private T info;
public Person(){}
public Person(T info){this.info=info;}
public void setInfo(T info){this.info=info;}
public T getInfo(){return info;}
3.从泛型类派生子类
public class A extends Person<T> //此种语法是错误的
public class A extends Person<String>
public class A extends Person //此处的T是object类型
4.“谨记”泛型类不存在
List<String> l1=new ArrayList<>();
List<Integer> l2=new ArrayList<>();
System.out.println(l1.getClass()==l2.getClass()); //此书输出true;
不管泛型的类型参数是什么,对于JAVA来说都是同一个类。 因此在静态方法、静态成员变量、静态初始化块处不能使用泛型
5.类型通配符
List<Integer>不允许赋给List<Number>
Integer[]可以赋给Number[];
为了解决上面的问题我们可以使用类型通配符?。比如List<String>、List<Integer>等都可以赋给List<?>。
public void test(List<?> c){
for(int i=0;i<c.size();i++)
System.out.println(c.get(i)); //此处取出的元素是Object类型的,并且不能把元素加入其中c.add(new Object())将引起编译错误,因为我们并不知道?代表何类型
}
6.类型通配符的上限和类型形参上限
method(List<? extends ClassA>);
public class Person<T extends ClassA>
7.泛型方法
public static <T> void fromArrayToCollection(T[] arr,Collection<T> col)
{
for(T o:arr){
c.add(o);
}
} //从数组取出元素放入集合。
泛型构造器
class Foo{
public <T> Foo(T t)
{
System.out.println(t);
}
}
new Foo("chensongxia"); //自动推断出T的类型是String
new <String> Foo("chensongxia"); //显示指出T的类型是String
new <String> Foo(12.3); //编译出错
当显示指出泛型构造的类型参数类型是=时不能使用“菱形”语法
class Person<E>
{
public <T> Person(T t){
System.out.println(t);
}
}
Person<String> p1=new Person<>(5); //E的类型是String,T的类型是Integer;
Person<String> p2=new <Integer> Person<String>(5);
Psrson<String> p3=new <Integer> Person<>(5); //此时菱形语法失效,要用上面的语法来定义。
8.通配符下限
public static <T> T copy(Collection<T> src,Collextion<? super T> dest)
9.泛型方法与重载
public static <T> void copy(Collection<T> dest,Collection<? extends T> src);
public ststic <T> void copy(Collection<? super T> dest,Collection<T> src); //包含这两个方法不会有任何错误,但是一旦调用他们就会引起编译错误
10.擦除与转换
class Person<T extends Number>{
...
}
Person<Integer> p1=new Person<>();
Person p2=p1; //此处p2不能记住泛型信息,即不知到T的类型是Integer,只知道是Number的子类
11.泛型与数组
不能实例化泛型类型的数组。例如:
- List<String>[] li = new ArrayList<String>[10];
12. 类的继承限定
形如以下代码的:
- class MyData<T extends Number & Serializable & Comparable<T>> {// do something...}