java的泛型是在JDK5开始出现的,在各种设计模式中有非常广泛的应用,比如设计一些基类等,参数化类型(具体的类型参数化)对扩展性能提供很好的支持,避免了不安全的强转安全风险。当然,在java中泛型是“假”的,最终会被擦除,本文就针对于此做一些“坑”的mark
下面使用List没有加泛型,存在风险
public static void main(String[] args) {
List list = new ArrayList();
list.add("1");
list.add(2);
List<String> list2 = list; //不报错 因为类型一样
list2.forEach(x -> System.out.println(x)); //报错 类型转换异常
}
下面对泛型的使用,一定要当心 小心传错值
public static void main(String[] args) {
Integer[] ints1 = new Integer[]{1, 2, 3};
int[] ints2 = new int[]{1, 2, 3};
doSomething(ints1); //输出1,2,3
doSomething(ints2); //输出[I@7cca494b
}
private static void doSomething(T... values) {
for (T value : values) {
System.out.println(value);
}
}
我们发现第二个输出直接把int[]数组的地址打印,因为int[]被作为一个类型值给传递了
public static void main(String[] args) {
List<String> stringArrayList = new ArrayList<>();
List<Integer> integerArrayList = new ArrayList<>();
Class<? extends List> aClass = stringArrayList.getClass();
Class<? extends List> bClass = integerArrayList.getClass();
System.out.println(aClass.isAssignableFrom(bClass)); //true
}
输出结果为true,有了上面的基础,这个结果此处就不做过多解释了 对此总结成一句话:泛型类型在逻辑上看以看成是多个不同的类型,实际上都是相同的基本类型。
静态方法上引用泛型,需要注意
public static class A<T> {
public static void get(Class<T> t){ //cannot be referenced from a static method
}
}
编译报错:静态方法不能在上下文里引用泛型类型
public static class A<T> {
public void get(Class<T> t){
}
}
这样写就没有毛病了(非静态方法可以直接引用)
public static class A<T> {
public static <E> void get(Class<E> t) {
}
}
如果即使是静态方法,但是将泛型定义在方法上就没问题了。注意:必须放在static关键字后面
综合上面所说,泛型的使用场景可以说是无处不在
泛型其实非常好用,保持良好的编码习惯可以减少出错,在实际的编程过程中,自己可以使用泛型去简化开发,且能很好的保证代码质量。更多泛型的基本使用,可参考链接:java泛型使用详解