📜  Java泛型-无例外(1)

📅  最后修改于: 2023-12-03 15:02:05.092000             🧑  作者: Mango

Java泛型-无例外

Java泛型是Java SE 5之后引入的一种语言特性,它允许我们在定义类、接口和方法时使用类型参数,使得我们可以以一种类型安全且通用的方式编写代码。本文将介绍Java泛型中的“无例外”。

泛型的类型擦除

在Java泛型中,虽然我们可以在代码中使用泛型类型参数,但是我们在实际运行时,却无法获取到泛型类型的具体信息。这是因为Java泛型采用了类型擦除的方式来实现,也就是将泛型类型在编译期间擦除,最终只保留一个类或接口的字节码。这个字节码中并不包含泛型的信息。

例如,下面的代码定义了一个泛型数组:

public class GenericArray<T> {
    private T[] array;

    public GenericArray(int size) {
        array = (T[])new Object[size];
    }

    public T get(int index) {
        return array[index];
    }

    public void set(int index, T value) {
        array[index] = value;
    }
}

在使用这个类的时候,我们可以定义一个Integer类型的GenericArray对象,如下所示:

GenericArray<Integer> intArray = new GenericArray<>(10);

在编译时,Java编译器会将该代码转换为以下代码:

GenericArray intArray = new GenericArray(10);

也就是说,泛型类型参数在编译后被擦除了,这是Java泛型的一个限制。

无例外的类型转换

由于Java泛型采用了类型擦除的方式,因此在某些情况下,我们需要手动进行类型转换。例如,如果我们想要将一个Object类型的值转换为泛型类型参数所表示的类型,我们可以使用强制类型转换,如下所示:

public T cast(Object obj) {
    return (T)obj;
}

但是,如果obj所代表的类型和T类型不一致,那么会发生ClassCastException异常。例如,下面的代码会抛出ClassCastException异常:

GenericArray<Integer> intArray = new GenericArray<>(10);
String s = "Hello World";
intArray.set(0, s);
Integer i = intArray.get(0); // ClassCastException

为了解决这个问题,Java泛型提供了“无例外”的方式。

我们可以在定义泛型类型参数时,使用通配符来限制其上界,如下所示:

public class GenericArray<T extends Number> {
    private T[] array;

    public GenericArray(int size) {
        array = (T[])new Number[size]; // 编译错误
    }

    public T get(int index) {
        return array[index];
    }

    public void set(int index, T value) {
        array[index] = value;
    }
}

在这个例子中,我们使用了extends关键字来限制T类型只能是Number或Number的子类。这样,我们在编写代码时就可以放心地将一个Number类型的值赋给T类型的引用变量,如下所示:

GenericArray<Integer> intArray = new GenericArray<>(10);
Number n = Integer.valueOf(42);
intArray.set(0, n); // 无例外
Integer i = intArray.get(0);

这段代码中,我们将一个Number类型的值赋给了一个Integer类型的变量,但是由于泛型类型参数被限制为Number或Number的子类,因此没有发生ClassCastException异常。

因此,无例外是Java泛型的一个非常重要的特性,它可以使我们编写更为类型安全的代码。