java 泛型的一系列问题
什么是泛型?为什么要使用泛型?
一、什么是泛型
最常见的例子:
1 |
List<String> list = new ArrayList<>(); |
这里的String类型就是一种泛型的实现。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 |
package testGeneric; public class Test { // 方法的泛型 public static <T> T get(T x) { System.out.println(x.getClass()); return x; } public static void main(String[] args) { System.out.println(get("string")); clazz clazz = new clazz("a", "b"); System.out.println(clazz.getFirst()); System.out.println(clazz.getSecond()); } } class clazz<A, B> { // 类的泛型 public A first; public B second; public clazz(A a, B b) { first = a; second = b; } public A getFirst() { return first; } public B getSecond() { return second; } } |
这里的get方法是一个泛型方法,clazz是一个泛型类。也可以将clazz称之为一个容器。
我个人认为:泛型可以是“任何类型”,只有在具体使用的时候才开始指定泛型的类型,从而提升了程序的灵活性,可以更好地实现重用。
二、为什么使用泛型
(1)灵活性
在上文的例子中:
1 2 3 4 5 6 7 |
// 方法的泛型 public static <T> T get(T x) { System.out.println(x.getClass()); return x; } |
因为可以通过getClass方法获取输入参数的类型,所以可以根据不同的参数采取不同的操作,从而使程序更加灵活,重用性更好
(2)规范数据的类型
参考:https://www.zhihu.com/question/23432488
编程的时候,能在编译时发现并修改错误最好,等上线运行时报错才解决,则属于生产事故,且找到bug的位置需要花费更多的时间和精力。
泛型是java1.5以后出现的内容。运用泛型,指定集合中的对象类型,你可以在编译时发现类型不匹配的错误,并且取数据时不需要手动强转类型。
举个例子:
如果在集合中不指定泛型,就可以add各种各样类型的数据:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
package testGeneric; import java.util.ArrayList; import java.util.List; public class test { public static void main(String[] args) { List list = new ArrayList<>(); list.add("a"); list.add(1); for (Object object : list) { System.out.println((String) object); } } } |
其结果是在取数据时会遇到很大的麻烦。我怎么知道当前object对象应该怎么转型呢?
1 2 3 |
aException in thread "main" java.lang.ClassCastException: java.lang.Integer cannot be cast to java.lang.String at testGeneric.test.main(test.java:17) |
为了规范集合的使用方式,可以使用泛型指定加入集合中数据的类型:
1 |
List<String> list = new ArrayList<>(); |
如果仍然尝试add一个1,在编译期间就会报出以下错误:
1 |
The method add(int, String) in the type List<String> is not applicable for the arguments (int) |
从而防止了直到运行期间才发现类型错误的情况,并且省去了逐一进行类型转换的麻烦。
三、泛型中的一些问题
个人认为泛型中的“通配符”和“边界”平时用得很少,但是概念比较难掌握,要用好确实不容易。体现为:上界通配符<? extends T>和下界通配符<? super T>。
对于这个问题,可以参考https://www.zhihu.com/question/20400700
我决定后面新开一篇文章来分析这个问题。
四、总结
泛型是非常重要的概念,必须掌握,并且灵活使用。