什么是泛型
Java泛型设计原则:只要在编译时期没有出现警告,那么运行时期就不会出现ClassCastException异常.
泛型:把类型明确的工作推迟到创建对象或调用方法的时候才去明确的特殊的类型
泛型简单来说就是参数化类型。如果我们日常使用的形参和实参一样,不过形参和实参是先先指定类型,然后到使用的时候再指定具体的值。而泛型就是将类型也参数化,我们实现类的时候先不指定固定的类型,等到实例化的时候再指定。
为什么需要泛型
其实你们会发现,其实在java中,如果不使用泛型也行,比如说直接用Object来代替,然后就可以在实例化的时候指定任意类型,这样好像也可以实现泛型的效果,但是这样会有些缺点,我们直接举个例子。
比如说我们要新建一个所有类型都可以用的List类,我们需要指定元素类型,这里我们用Object来声明,这样会有啥问题呢?
1.Object的指定的范围太广了,比如说我List里面可以add一个Cat,我又可以add一个Dog,编译器是不会报错的,这样如果出现了问题也很难排查。
2.如果我们get一个元素出来,我们清楚元素的类型还好,可以直接强转,如果不清楚的话就头大了。
所以使用泛型的好处:
- 代码更加简洁【不用强制转换】
- 程序更加健壮【只要编译时期没有警告,那么运行时期就不会出现ClassCastException异常】
- 可读性和稳定性【在编写集合的时候,就限定了类型】
泛型的使用
泛型接口
public interface Map<K, V> {
public void put(K key, V value);
public V get(K key);
}
泛型类
/*
1:把泛型定义在类上,如果想要多个泛型的话,可以以逗号相隔,如:<T,V,K>
2:类型变量定义在类上,方法中也可以使用
3:到时候使用的话,可以Test t = new Test<Integer>();这样子就可以指定T的类型了
*/
public class Test<T> {
private T obj;
public T getObj() {
return obj;
}
public void setObj(T obj) {
this.obj = obj;
}
}
泛型方法
/**直接在返回值的前面指定泛型,然后就可以在形参中使用了,
这里的使用方式是:xxx.show(Integer i);
这样就指定了T的类型了,就可以使用了。
**/
public <T> void show(T t) {
System.out.println(t);
}
限制泛型的类型
有时候我们希望限制泛型的类型是在一定的范围下,这时候我们就需要用到限定符。
如果我们需要限制泛型需要全部是F类的子类的话,我们就可以这样指定:
< ? extends F>
反之,如果需要全部是S类的父类的话,我们可以:
<? super S>
获取泛型
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
public class Main {
public static void main(String[] args) throws Exception {
Class clazz = new B().getClass();
//因为直接拿出来的是Type,所以向下强转
ParameterizedType superclass = (ParameterizedType) clazz.getGenericSuperclass();
Type[] types = superclass.getActualTypeArguments();//得到所有参数
Class zz = (Class)types[0];//因为只有一个泛型,所以这里直接用0拿到
System.out.println(zz);
}
}
class A<T> {}
class B extends A<String> {}