引言
Java泛型是JDK 5.0引入的一个新特性,它允许在定义类、接口和方法时使用类型参数(type parameters)。这种参数化类型可以在类声明、接口声明、方法声明中作为类型使用,它们被称为泛型。泛型的主要目标是提高代码的可重用性、类型安全性以及减少类型转换和强制类型转换的错误。
泛型的基本使用
泛型类
泛型类就是在类定义时通过类型参数声明来指示类中要使用的类型,然后在类定义的方法中使用该类型参数。
示例代码:
代码语言:java复制public void set(T t) { this.t = t; }
public T get() { return t; }
public static void main(String[] args) {
Box<Integer> integerBox = new Box<Integer>();
integerBox.set(new Integer(10));
Integer i = integerBox.get();
System.out.println(i.intValue());
Box<String> stringBox = new Box<String>();
stringBox.set("Hello World");
String s = stringBox.get();
System.out.println(s);
}
}
泛型接口
泛型接口与泛型类类似,在接口定义时声明类型参数。
示例代码:
代码语言:java复制public interface List<T> {
void add(T item);
T get(int index);
// ... 其他方法
}
// 实现泛型接口的类
public class ArrayList<T> implements List<T> {
// ... 实现方法
}
泛型方法
泛型方法是在方法中声明类型参数的方法。
示例代码:
代码语言:java复制public class Util {
public static <T> T getMiddle(T... a) {
return a[a.length / 2];
}
public static void main(String[] args) {
System.out.println(Util.getMiddle("a", "b", "c", "d", "e")); // 输出 "c"
System.out.println(Util.getMiddle(1, 2, 3, 4, 5)); // 输出 3
}
E (Element)
}
E通常用于表示集合中的元素类型。例如,在List<E>、Set<E>等集合类中,E就是用来表示集合中元素的类型。
在这里,String就是E的具体类型。
V通常用于表示值类型,特别是在映射(Map)中。在Map<K, V>中,K表示键的类型,而V表示值的类型。
K通常用于表示键的类型,特别是在映射(Map)中。如上所述,在Map<K, V>中,K就是键的类型。
需要注意的是,虽然E、V和K在Java的集合框架中有一定的约定俗成的用法,但它们并不是Java语言本身强制规定的。在自定义泛型类、接口或方法时,你可以使用任何字母作为类型参数的标识符,只要确保在整个类或方法中保持一致即可。
##泛型的高级特性
通配符
Java中提供了两种通配符:?(无界通配符)和? extends T(有界通配符)。通配符主要用于泛型方法的参数传递。
代码语言:java复制无界通配符
List<?> wildcardList = new ArrayList<String>();
上界通配符
表示该泛型可以是 T 或 T 的子类。
public class Main {
public static void process(List<? extends Number> numbers) {
// 可以进行只读操作
}
}
下界通配符
下界通配符(? super T):表示该泛型可以是 T 或 T 的父类。
public class Main {
public static void addElements(List<? super Integer> list) {
list.add(10);
}
}
类型擦除
由于Java的泛型是在编译时实现的(称为类型擦除),因此运行时并不知道泛型类型的信息。这意味着你不能在运行时检查泛型类型或进行类型转换。但是,你可以通过添加类型标签(Type Tag)或使用instanceof操作符结合原始类型(raw type)进行类型检查。
泛型与数组
Java中不能创建泛型数组,因为类型擦除导致运行时无法确定数组元素的类型。但是,你可以创建原始类型的数组,并在泛型类中作为成员变量使用。
总结
Java泛型是一个强大的工具,它提高了代码的可重用性、类型安全性和可读性。通过正确地使用泛型,我们可以编写更加健壮和灵活的代码。然而,也需要注意泛型的一些限制和陷阱,比如类型擦除和不能创建泛型数组等。
我正在参与2024腾讯技术创作特训营最新征文,快来和我瓜分大奖!