假如Java没有泛型
阅读 1.6k
对于Java中的泛型,估计大家都习以为常了,但如果Java中没有泛型,会怎么样呢?
没有泛型之前
Java5推出了泛型,在这之前,泛型是使用继承
的方式来进行模拟的:
class ArrayLis {
private Object[] elementData;
public ArrayLis() {
elementData = new Object[]{"foo.md", "bar.png"};
}
public Object get(int i) {
return elementData[i];
}
public void set(int i, Object obj) {
elementData[i] = obj;
}
}
如上,定义了一个ArrayLis类,它其中的元素都是Object类型,使用起来也很简单,如下:
ArrayLis files = new ArrayLis();
files.set(0, "test.png");
String filename = (String) files.get(0);
System.out.println(filename);
files.set(1, 100);
int num = (int) files.get(1);
System.out.println(num);
这种模拟方式有两个讨厌的问题:
第一,对获得的值需要进行强制类型转换
,如上,索引0处为String类型,需要对其用 (String) 进行强制转换;
第二,因为没有错误检查,你可以向files对象中添加任何类型的值,添加时不会报错,比如上面代码,添加了两种类型,一种是String,一种是int,如果在其他地方使用时,将索引0处的类型不小心当作int类型来处理,就会报错。
很明显,这种模拟的方式会导致了代码变得混乱,我们需要一种更准确
的方式来指定每种类型,因此,Java 5推出了泛型。
有了泛型之后
有了泛型之后,同样的例子,我们来看看有啥区别:
public class ArrayLis2<T> {
private T[] elementData;
public ArrayLis2(Class<T> clz) {
elementData = (T[]) Array.newInstance(clz, 2);
}
public T get(int i) {
return elementData[i];
}
public void set(int i, T item) {
elementData[i] = item;
}
}
首先,我们定义一个泛型类ArrayLis2,菱形括号中的T表示类型,使用如下:
ArrayLis2<String> files = new ArrayLis2<>(String.class);
// 1. 不再需要用(String)来强制类型转换
files.set(0, "foo.png");
String filename = files.get(0);
System.out.println(filename);
// 2. 同时,明确指定了files中的数据是String类型,那么插入其他类型会报错:
int foo = 12;
System.out.println(foo);
files.set(1, foo); // java: incompatible types: int cannot be converted to java.lang.String
因为指定了files中的数据是String类型的,当插入int类型的值时,编辑器会报错:incompatible types: int cannot be converted to java.lang.String
,这样,提前将错误暴漏了出来。
另外,Java本身也提供了很多泛型类,比如:ArrayList等。
参考
- Core Java Volume I Fundamentals, 11th Edition,Cay S. Horstmann
最后编辑于: 2023-07-17