📅  最后修改于: 2023-12-03 15:02:05.092000             🧑  作者: Mango
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泛型的一个非常重要的特性,它可以使我们编写更为类型安全的代码。