泛型类是指具有一个或多个类型参数的类。通过使用类型参数,可以在实例化时指定具体的类型,从而实现代码的通用性和类型安全性。
泛型类的定义格式如下:
public class 类名<类型参数1, 类型参数2, ...> { // 类的成员变量、方法等 }
其中,类型参数可以是任意合法的 Java 标识符,通常使用单个大写字母来表示,例如 T、E、K 等。
在泛型类中,可以使用类型参数来定义类的成员变量、方法参数、方法返回值等。在实例化泛型类时,可以指定具体的类型来替换类型参数。
下面是一个示例,定义了一个泛型类 Box,用于存储任意类型的对象:
public class Box<T> { private T item; public void setItem(T item) { this.item = item; } public T getItem() { return item; } }
在上面的例子中,Box 类使用了类型参数 T,表示存储的对象的类型。通过 setItem 方法和 getItem 方法,可以设置和获取存储的对象。
可以通过以下方式实例化泛型类 Box:
// 使用整形对象实例化 Box Box<Integer> intBox = new Box<Integer>(); intBox.setItem(10); int item = intBox.getItem(); // 返回 10 // 使用字符串类型实例化 Box Box<String> stringBox = new Box<String>(); stringBox.setItem("Hello"); String item = stringBox.getItem(); // 返回 "Hello"
通过指定具体的类型参数,可以在实例化时确定存储对象的类型,并保证类型安全性。
通过使用泛型类,可以实现对不同类型的支持,提高代码的可维护性和可靠性。泛型类具有以下优点:
(1)代码重用性:泛型类可以在不同的场景下使用相同的代码逻辑,只需通过指定不同的类型参数来实现对不同类型的支持。这样可以减少重复编写类似的代码,提高代码的重用性。
(2)类型安全性:泛型类在编译时进行类型检查,可以在编译阶段捕捉到类型错误,避免在运行时出现类型转换异常。这样可以提高代码的健壮性和可靠性。
(3)简化代码:泛型类可以通过类型参数来减少代码量和代码复杂性。通过使用泛型,可以避免手动进行类型转换和类型判断的繁琐操作,使代码更加简洁和易读。
(4)提供编译时类型检查:泛型类可以在编译时对类型进行检查,确保在使用泛型类时传入的类型符合预期。这样可以避免在运行时出现类型错误,提高代码的可靠性和可维护性。
(5)提高性能:泛型类在编译时会进行类型擦除,将泛型类型转换为原始类型。这样可以避免在运行时进行类型检查和类型转换的开销,提高代码的执行效率。
泛型类通配符是一种特殊的类型参数,用于在泛型类中表示未知类型或限制类型的上界或下界。通配符使用 “?” 符号表示。
通配符可以分为两种类型:无界通配符和有界通配符。
使用`?`表示,表示未知类型。在泛型类中使用无界通配符,可以接受任意类型的对象。
public class Box<T> { public void doSomething(Box<?> box) { // 处理box中的对象,但无法确定具体类型 } }
在上面的例子中,doSomething 方法接受一个类型为 Box<?> 的参数,可以处理任意类型的 Box 对象,但无法确定具体的类型。
使用 “? extends 类型” 表示上界通配符,使用 “? super 类型” 表示下界通配符。有界通配符用于限制泛型类的类型参数的范围。
表示泛型类的类型参数必须是指定类型或其子类型。
public class Box<T extends Number> { public void doSomething(Box<? extends Number> box) { // 处理box中的对象,可以确定是Number类型或其子类型 } }
在上面的例子中,doSomething 方法接受一个类型为 Box<? extends Number> 的参数,可以处理存储了 Number 类型或其子类型的 Box 对象。
表示泛型类的类型参数必须是指定类型或其父类型。
public class Box<T super Integer> { public void doSomething(Box<? super Integer> box) { // 处理box中的对象,可以确定是Integer类型或其父类型 } }
在上面的例子中,doSomething 方法接受一个类型为 Box<? super Integer> 的参数,可以处理存储了 Integer 类型或其父类型的 Box 对象。