什么是泛型
Java 泛型(generics)是 JDK 5 中引入的一个新特性, 泛型提供了编译时类型安全检测机制,该机制允许程序员在编译时检测到非法的类型。
泛型的本质是参数化类型,也就是说所操作的数据类型被指定为一个参数。
泛型还是一种把类型的明确工作推迟到创建对象或者调用方法的时候才去明确的特殊类型。
为什么要使用泛型
在java早期开发的时候,常常使用Object来代表任意的类型,虽然这样在向上转型上没有问题,但是在进行向下转型时会出现类型转换的问题,并时程序陷入不安全的状态。
实例分析
{
private object[] m_item;
public object Pop(){...}
public void Push(object item){...}
public Stack(int i)
{
this.m_item = new[i];
}
}
上面这个栈可以非常灵活地接受任意的数据类型,但是当它处理值类型时,出现装修、拆箱操作后,这时候用到的强制转换操作,会出现严重的问题。
stack.Push(x);
Node2 y = (Node2)stack.Pop();
上面的代码在编译时是完全没问题的,但由于Push了一个Node1类型的数据,但在Pop时却要求转换为Node2类型,这将出现程序运行时的类型转换异常,但却逃离了编译器的检查。
因此,在JDK1.5之后,加入了泛型来解决类似的问题。例如在上述问题中便可以使用泛型:
{
private T[] m_item;
public T Pop(){...}
public void Push(T item){...}
public Stack(int i)
{
this.m_item = new T[i];
}
}
这样,类的写法不变,仅仅只是引入了通用数据类型T就可以适用于任何数据类型,并且类型安全的。
泛型的使用
泛型类
格式:public class 类名<参数类型,…>{} (<>里面也可以使用多个不同参数类型例如:public class User<T,E>{})
注意:类型变量使用大写形式,且比较短,这是很常见的。在Java库中,使用变量E表示集合的元素类型,K和V分别表示关键字与值的类型。(需要时还可以用临近的字母U和S)表示“任意类型”。
public class ObjectTool<T>
{
private T obj;
public void setObj(T obj) {
this.obj = obj;
}
public T getObj() {
return obj;
}
}
public static void main(String[] args) {
ObjectTool<String> obj = new ObjectTool<>();
obj.setObj("Hello World.");
System.out.println(obj.getObj());
}
泛型方法
格式:public 返回值 方法名(T a){}
public <E> void show(E s)
{
System.out.println(s);
}
public static void main(String[] args) {
ObjectTool obj = new ObjectTool();
obj.show("Hello world.");
obj.show(100);
}
泛型通配符
类型通配符一般指使用<?>来代替具体的类型参数。比如List<?>逻辑上是List< String >, List< Integer >等的父类
//泛型如果明确的写的时候,前后类型必须一致
Collection<Object> c1 = new ArrayList<Object>();
Collection<Object> c2 = new ArrayList<Animal>(); //报错
Collection<Object> c3 = new ArrayList<Dog>(); //报错
//?表示任意类型都是可以的
Collection<?> c4 = new ArrayList<Object>();
Collection<?> c5 = new ArrayList<Animal>();
Collection<?> c6 = new ArrayList<Dog>();
<? extends T>:向下限定,只能是E及其子类
Collection<? extends Animal> c1 = new ArrayList<Object>(); //报错
Collection<? extends Animal> c2 = new ArrayList<Animal>();
Collection<? extends Animal> c3 = new ArrayList<Dog>();
Collection<? extends Animal> c4 = new ArrayList<Cat>();
<? super T>:向上限定,只能是E及其父类
Collection<? super Animal> c1 = new ArrayList<Object>();
Collection<? super Animal> c2 = new ArrayList<Animal>();
Collection<? super Animal> c3 = new ArrayList<Dog>(); //报错
Collection<? super Animal> c4 = new ArrayList<Cat>(); //报错
Java泛型的实际使用
下面给出设计的一个泛型的获取数组最小值的函数.并且这个方法只能接受Number的子类并且实现了Comparable接口。
public class Generic {
public static <T extends Number & Comparable<? super T>> T Generic(T[] values){
if(values == null || values.length == 0)
return null;
else{
T min = values[0];
for(int i = 0; i < values.length;i++)
{
if(min.compareTo(values[i])>0)
min = values[i];
}
return min;
}
}
public static void main(String[] args){
int minInteger = Generic(new Integer[]{1,2,3});
//String minString = Generic(new String[]{"1","3"});(Error)
System.out.println(minInteger);
}
}