假如Java没有泛型

阅读 1.6k
标签: Java

对于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

评论(0条)

(必填)
复制成功