如果你写过前端,可能会经常写一下关于变量类型的判断,比如:typeof fn === 'function'
之类的代码。因为JavaScript作为一门弱类型语言,类型的判断往往需要开发人员自己去检查。
Java作为一门强类型语言,它的强就强在类型的约束比较严格,大多都是在编译器(IDEA、eclipse...)里就做了检查,也就是说你刚敲完一个字符,如果有类型错误,下一秒就能提示你哪错了。这也避免了运行时的错误,让你的代码更加的严谨。下面就来了解一下为类型约束做出卓越贡献的人物——泛型。
Java泛型为何而生
Java泛型(generics)是JDK 1.5中引入的一个新特性,泛型提供了编译时类型安全检测机制,该机制允许程序员在编译时检测到非法的类型。泛型的本质是参数化类型,也就是说操作的数据类型被指定为一个参数。
我知道,上面那些干巴巴的概念对于初学者看了也是一头雾水。下面让我们穿越回到JDK 1.5之前的时代,当初还没有泛型的存在,我们是怎么生活的呢?
泛型解决了哪些痛点
ArrayList
可以看做“可变长度”的数组,用起来比数组方便。实际上,ArrayList
内部就是一个Object[]
数组,配合存储一个当前分配的长度,就可以充当“可变数组”:
public class ArrayList {
private Object[] array;
private int size;
public void add(Object e) {...}
public void remove(int index) {...}
public Object get(int index) {...}
}
如果有上面的ArrayList
存储String
类型,会有这么几个缺点:
- 需求强制手动转型
- 不方便,易出错
例如,代码必须这么写:
ArrayList list = new ArrayList();
list.add("Hello");
// 获取到Object,必须强制转型为String:
String first = (String) list.get(0);
很容易出现ClassCastException
,因为容易“误转型”:
list.add(new Integer(123));
// ERROR: ClassCastException:
String second = (String) list.get(1);
要解决上面的问题,我们可以为String
单独编写一种ArrayList
:
public class StringArrayList {
private String[] array;
private int size;
public void add(String e) {...}
public void remove(int index) {...}
public String get(int index) {...} // 注意这个特意做了处理
}
这样一来,存入的必须是String
,取出的也一定是String
,不需要强制转型,因为编译器会强制检查放入的类型:
StringArrayList list = new StringArrayList();
list.add("Hello");
String first = list.get(0);
// 编译错误: 不允许放入非String类型:
list.add(new Integer(123));
好了,虽然没有用泛型,但是借助劳动人民的智慧结晶,我们也能把这个问题解决掉